Polymorphic setter for Boost::variant
Polymorphic setter for Boost::variant
我试图使用boost::模板类型的变体。例如,我有一个模板类型Tag<T>
和boost::变体AnyTag包括Tag<double>
, Tag<int>
和Tag<std::string>
等类型。每个Tag<T>
都有类型为T的成员。现在,我想把这些变量放在一个容器中,并在运行时简单地赋值,例如,
for(AnyTag & tag: AllTags) {
setValue(tag, getValueFromXml());
}
函数setValue(AnyTag &tag, T &val)
必须使用AnyTag标签的运行时类型,以便正确地为标签分配正确的值。我解决问题的尝试可以在下面找到,它使用了另一种变体,其中只包括可以在AnyTag (TagValueType)中使用的可能的T类型。
template<typename T, typename = void>
class Tag {};
template <typename T>
class Tag<T, EnableIf<std::is_arithmetic<T>>> {
public:
T value = 0;
std::string address = "";
T maxValue = std::numeric_limits<T>::max();
typedef T value_type;
};
template <typename T>
class Tag<T, DisableIf<std::is_arithmetic<T>>> {
public:
T value;
std::string address = "";
typedef T value_type;
};
typedef boost::variant<Tag<std::string>,
Tag<double>,
Tag<int>,
> AnyTag;
typedef boost::variant<std::string, double, int> TagValueType;
class tag_set_value_visitor: public boost::static_visitor<void>
{
const TagValueType & value;
public:
tag_set_value_visitor(const TagValueType & val): value(val){}
template <typename T>
void operator()(T & tag) const
{
tag.value = boost::get<typename T::value_type>(value);
}
};
inline void setValue(AnyTag & tag, const TagValueType & val) {
assert(tag.which() == val.which());
boost::apply_visitor( tag_set_value_visitor(val), tag );
}
不幸的是,这种方法不是我想要的,因为例如,在编译过程中,如果我执行以下操作,就不会出现问题:
AnyTag a = Tag<int>();
setValue(a, double(1.3));
但是在运行时,boost库检测到类型不匹配并崩溃程序。
所以,我的解决方案是一种类型擦除,只是推迟了问题。我想要的是一个setValue(AnyTag &tag, T &val),其中T是AnyTag的运行时类型。
我知道这就是变量的访问者试图做的,但是在这种情况下有一个问题,因为当我们构造访问者时,我们必须知道我们将要使用的类型。
关于这个问题有什么想法吗?注:
使用二进制访问器
实现operator()
除了对应的类型之外什么都不做。
处理不匹配的味道(我返回一个布尔值表示成功):
Live On Coliru
#include <boost/any.hpp>
#include <boost/variant.hpp>
#include <boost/mpl/vector.hpp>
#include <string>
using namespace boost;
template <typename T>
struct Tag {
T value;
};
using Types = mpl::vector<std::string, double, int>;
using Tags = mpl::transform<Types, Tag<mpl::_1> >::type;
using Variant = make_variant_over<Types>::type;
using AnyTag = make_variant_over<Tags>::type;
namespace mydetail {
struct assign_to : boost::static_visitor<bool> {
template <typename V> bool operator()(Tag<V>& tagged, V const& value) const {
tagged.value = value;
return true;
}
template <typename T, typename V> bool operator()(T&&, V&&) const {
return false;
}
};
}
bool setValue(AnyTag &tag, Variant const& val) {
return boost::apply_visitor(mydetail::assign_to(), tag, val);
}
int main() {
AnyTag t;
t = Tag<std::string>();
// corresponding type assigns and returns true:
assert(setValue(t, "yes works"));
// mismatch: no effect and returns false:
assert(!setValue(t, 42));
assert(!setValue(t, 3.1415926));
}
如果我没理解错的话。我关注的是"我想要的是一个setValue(AnyTag &tag, T &val),其中T是AnyTag的运行时类型。"
相关文章:
- boost::spirit::karma 替代生成器,带有 boost::variant 由字符串和字符串别名组成
- 在 boost::variant 中类 holden 的复制构造函数存在问题
- boost::variant - 如何分配值
- boost::variant - 对变体应用算术的最简单方法
- Boost Variant 是否提供与 std holds_alternative类似的功能?
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- 为什么Boost Variant使用模板构造函数而不是Boost::beast::websocket::stream的移
- SWIG and Boost::variant
- 从 boost::variant 中逐个索引获取项目,就像使用 std::variant 一样
- "非静态数据成员之前需要构造函数" - 我是否使用"boost::variant"
- boost::variant 当 bool 显示为可能的类型时,会给出错误的结果
- 使用 boost::variant 并获取泛型返回类型
- 使用 boost::variant 调用模板类函数
- boost::variant 是否仍用于野外的新项目?
- 如何实现 boost::variant 派生类
- 获取 boost::variant 的类型索引与 boost::mpl
- decltype 和 boost::variant - 检索当前值
- QVariant vs boost::any vs boost::variant
- 使用Boost :: black在boost :: variant中使用时,请警告编译器
- Getter for boost::variant object