I am trying to use boost :: variant with template types. For example, I have a template type Tag<T> , and boost :: variant AnyTag contains types such as Tag<double> , Tag<int> and Tag<std::string> . Each Tag<T> has members of type T. Now I would like to put these options in a container and just assign values ββat runtime, like
for(AnyTag & tag: AllTags) { setValue(tag, getValueFromXml()); }
The setValue(AnyTag &tag, T &val) function setValue(AnyTag &tag, T &val) must use the execution type of the AnyTag tag to correctly assign the tag the correct value. My attempt to solve the problem can be found below, and it uses another option, which includes only the possible types of T that can be used in AnyTag (TagValueType).
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 ); }
Unfortunately, this approach is not what I would like, because, for example, there is no problem during compilation if I do the following:
AnyTag a = Tag<int>(); setValue(a, double(1.3));
but at runtime, the acceleration library detects a type mismatch and displays a program failure message.
So my solution is a kind of type erasure that just postpones the problem.
What I would like to have is setValue (AnyTag & tag, T & val), where T is the type of the AnyTag runtime.
I get what the visitor of the option tries to try, but in this case there is a problem, because when we build the visitor, we need to know the type that we will use.
Any ideas or any thoughts on this issue?
PS: Sorry for the long post, but I could not find a way to explain my thought process with fewer words.