boost::variant 将 static_visitor 应用于某些类型
Posted
技术标签:
【中文标题】boost::variant 将 static_visitor 应用于某些类型【英文标题】:boost::variant apply static_visitor to certain types 【发布时间】:2020-11-29 18:25:23 【问题描述】:我有以下变体:
typedef boost::variant<int, float, bool> TypeVariant;
我想创建一个访问者来将int
或float
类型转换为bool
类型。
struct ConvertToBool : public boost::static_visitor<TypeVariant>
TypeVariant operator()(int a) const
return (bool)a;
TypeVariant operator()(float a) const
return (bool)a;
;
但是这给了我错误信息:
'TypeVariant ConvertToBool::operator ()(float) const': 无法将参数 1 从 'T' 转换为 'float'
允许访问者仅适用于某些类型的正确方法是什么?
【问题讨论】:
为什么不简单地将 bool 转换为 bool?另外,请考虑返回 bool 而不是变体。 @Yakk-AdamNevraumont 将 bool 转换为 bool 是什么意思? 【参考方案1】:只需包含缺少的重载:
Live On Coliru
#include <boost/variant.hpp>
#include <iostream>
using TypeVariant = boost::variant<int, float, bool>;
struct ConvertToBool
using result_type = TypeVariant;
TypeVariant operator()(TypeVariant const& v) const
return boost::apply_visitor(*this, v);
TypeVariant operator()(int a) const return a != 0;
TypeVariant operator()(float a) const return a != 0;
TypeVariant operator()(bool a) const return a;
static constexpr to_bool;
int main()
using V = TypeVariant;
for (V v : V, 42, 3.14f, true)
std::cout << v << " -> " << std::boolalpha << to_bool(v) << "\n";
概括
在更一般的情况下,您可以提供包罗万象的模板重载:
template <typename T> TypeVariant operator()(T const& a) const
return static_cast<bool>(a);
事实上,在你的微不足道的情况下,这就是你所需要的一切:
Live On Coliru
#include <boost/variant.hpp>
#include <iostream>
using TypeVariant = boost::variant<int, float, bool>;
struct ConvertToBool
using result_type = TypeVariant;
TypeVariant operator()(TypeVariant const& v) const
return boost::apply_visitor(*this, v);
template <typename T> TypeVariant operator()(T const& a) const
return static_cast<bool>(a);
static constexpr to_bool;
int main()
using V = TypeVariant;
for (V v : V, 42 , 3.14f , true )
std::cout << v << " -> " << std::boolalpha << to_bool(v) << "\n";
仍然打印
0 -> false
42 -> true
3.14 -> true
true -> true
【讨论】:
非常感谢您的详细回答。是的,这个布尔转换示例只是我的实际问题的简化问题,这些示例完美地回答了这些问题。关于您的第一个示例,我还有一个问题:当我将std::string
添加到变体中,并且未能为其指定运算符重载时,将std::string 传递给to_bool
时,它返回true。为什么会这样?我希望它会崩溃,因为没有指定重载。
我希望它不会编译,不会崩溃。但显然,是的,有一个漏洞导致它成为UB:见SEGV on Coliru。启用 asan/ubsan shows what's going on:它只是反复击中 VariantType
过载。我以前没有意识到这是该方法的潜在错误源(在可调用类型中执行apply_visitor
)。
我通常是这样设置的:coliru.stacked-crooked.com/a/8efbacc6526acad6 - 单独的(私有的和潜在的静态的)call
实现prevent the infinite recursion [现在它不编译]。除了这个习惯用法之外,通过递归变体实现访问者也很优雅,因为例如return call(x) + call(y)
看起来比 return operator()(x) + operator()(y)
好,甚至更差 return (*this)(x) + (*this)(y);
以上是关于boost::variant 将 static_visitor 应用于某些类型的主要内容,如果未能解决你的问题,请参考以下文章
boost::variant 将 static_visitor 应用于某些类型
使用 boost::variant 库制作地图。如何将事物存储和显示为正确的类型?