[Please avoid top-posting;
http://www.boost.org/community/policy.html#quoting]
On Wed, Jul 11, 2012 at 2:10 PM, Petros
Jeff, Thank you very much for responding. I tried containment, instead of inheritance, as you suggest, getting the same error messages.
Ummm...are you sure? The following compiles fine for me on MSVC9 (note
copious additional fixes which did not include fixing the template
parameter shadowing):
--------
#include
Tried to substitute the templated c/tors/assignment operators but w/out (good) result.
What do you mean? I believe that the real issue is that the c/tor in variant is templated.
The problem isn't the templatization per se, it's the unconstrainedness of the templated constructor (IIRC) :/
As far as the identical template arguments for variant, maybe a c/tor with the (0-based ?) type could be of use.
You mean the first type in the sequence of value types that is convertible from the argument? That's possible, but I don't believe boost::variant presently attempts to do that. You can always try!
Imagine the amount of complexity that is generated, by trying to write template expressions where arguments may just happen to be the same (of course, I know nothing on the implementation details of variant – so I may well be waaaay off [image: Winking smile])
I don't think it's too difficult to write a metafunction that generates the desired variant, and all the complexity would be isolated to that metafunction. Finally, I am only interested about compile time “polymorphism”.
Hmmm...then why are you using variant?
The real motivation of all this is that, I have expressions that can sometimes generate a unit/zero vector (like in a Monte-Carlo simulation) and want to maintain a uniform interface across expressions that generate this “vector” (hence the variant) -nothing terribly original [image: Winking smile])
Well, variant essentially erases the type of the object it's constructed with, so you're effectively using runtime polymorphism (though of a more controlled nature than boost::any or virtual functions). I don't know enough about the particulars of your application based on your description above to know if that's appropriate.
So, do you think that this construct will be optimized away at compile time ( for me the variants can as well be no-re-assignable) ?
I still don't know what you want optimized away. Thank you very much for taking the trouble to look into it,
Petros
PS: google search indicated that this kind of problem was attributed to the msvc compiler misusing the base templated c/tors. However, the result is identical with the intel 12.1 compiler (not that it cannot suffer from the same issue).
It's a related but distinct issue in this case.
*From:* Jeffrey Lee Hellrung, Jr.
*Sent:* Wednesday, July 11, 2012 4:10 PM *To:* boost-users@lists.boost.org *Subject:* Re: [Boost-users] compilation problem and a couple ofboost::variant questions On Wed, Jul 11, 2012 at 11:32 AM, Petros
wrote: Hi, I am trying to write some operator that multiplies two variants, each one containing a vector a zero and a unit, where I am trying to use the fact that I know the outcome for multiplying by 0 or by 1. The code (very bare bones) below describes how this is done, by: _ defining dummy structures of Variant-1, 2 _ defining a class that contains the instruction for multiplication _ defining a class (derived from variant) that contains possible outcomes of the multiplication _ defining the operator (only a few of the possible outcomes are shown) Compiling with msvc2010 (intel has similar issues) on win7: First here is the code:
#include
using boost::variant; struct Zero1{ double operator[]( const size_t i ) const { return 0L ; } }; struct One1{ double operator[]( const size_t i ) const { return 1L ; } }; struct Zero2{ double operator[]( const size_t i ) const { return 0L ; } }; struct One2{ double operator[]( const size_t i ) const { return 1L ; } }; struct Vector1{ double operator[]( const size_t i ) const {return double( i ) ; } }; struct Vector2{ double operator[]( const size_t i ) const {return double( 2*i ) ; } }; struct subscript_operator:public boost::static_visitor<double>{ const size_t i_; subscript_operator( const size_t i ):i_(i){}
template<typename _v> double operator()( _v const & v ) const { return v[i] ; } };
template
class VariantT :public variant< _V, _Z, _U > I believe the fact that VariantT<> inherits from boost::variant (combined with the structure of the boost::variant implementation) is the cause of the ambiguity in convert_construct referenced below. For example, the following minimal code produces the same problem:
#include
struct X : boost::variant< int > { };
void main() { X x; boost::variant<X> y(x); }
I'll file a trac ticket against boost::variant; in the meantime, try making boost::variant a member object rather than a base object.
[...snip remaining code...]
And here is one of the errors :
boost_1_49_0\boost\variant\variant.hpp(1399): error C2666: 'boost::variant
::convert_construct' : 2 overloads have similar conversions 1> with 1> [ 1> T0_=MultVarVar , 1> T1=Zero1, 1> T2=One1, 1> T3=Variant1, 1> T4=Variant2 1> ] 1> c:\_petros\_otc\ext\boost_1_49_0\boost\variant\variant.hpp(1384): could be 'void boost::variant ::convert_construct<_V,_Z,_U,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_>(const boost::variant<_V,T1,T2> &,long)' 1> with 1> [ 1> T0_=MultVarVar , 1> T1=Zero1, 1> T2=One1, 1> T3=Variant1, 1> T4=Variant2, 1> _V=Vector1, 1> _Z=Zero1, 1> _U=One1 1> ] 1> c:\_petros\_otc\ext\boost_1_49_0\boost\variant\variant.hpp(1315): or 'void boost::variant ::convert_construct<const T>(T &,int,boost::mpl::false_)' 1> with 1> [ 1> T0_=MultVarVar , 1> T1=Zero1, 1> T2=One1, 1> T3=Variant1, 1> T4=Variant2, 1> T=Variant1 1> ] 1> while trying to match the argument list '(const Variant1, long)' 1> c:\_petros\_otc\tests\variant\variant\main.cpp(120) : see reference to function template instantiation 'boost::variant ::variant<_V>(const T &)' being compiled 1> with 1> [ 1> T0_=MultVarVar , 1> T1=Zero1, 1> T2=One1, 1> T3=Variant1, 1> T4=Variant2, 1> _V=Variant1, 1> T=Variant1 1> ] 1> c:\_petros\_otc\tests\variant\variant\main.cpp(151) : see reference to function template instantiation 'MultVarVarResult<_V1,_V2>::MultVarVarResult<_V1>(const _V &)' being compiled 1> with 1> [ 1> _V1=Variant1, 1> _V2=Variant2, 1> _V=Variant1 1> ] 1> Any help on this will be greatly appreciated! And the questions: What happens if a variant contains two identical template arguments ? when I create a (variant) object from one of the two identicals, how does it know which template argument I need ?
It probably doesn't :) My guess is you'll get some compiler errors based on ambiguous overloads (distinct but similar to the errors above). I think your best bet is to preprocess the sequence of value types to remove duplicate types prior to generating your variant type. You can do this via Boost.MPL, e.g., the documentation for boost::mpl::set<> [1] has an example to this effect, and then you may use boost::make_variant_over [2].
Do I have to write the same code for the specialization of identical _V1 and _V2?
That or complicate the generation of the variant type, as I've described above.
Also, am I correct to assume that all this syntax ( element-wise static_visitor’s etc) will be optimized away at a release build ?
I'm not sure what you're looking to have optimized away. If you mean that the compiler can somehow deduce at compile time the runtime underlying type of the variant based on your code in main and somehow optimize away the runtime dispatching...I guess that's possible, but I wouldn't depend on it or care, as I can't think of a reason you'd use a boost::variant in such a scenario other than for testing. On the other hand, if it's impossible to know the runtime underlying type of the variant, then there's no way to get around the runtime dispatching.
However, I would expect any decent compiler to collapse all statically known calls before and after the runtime dispatch, if that's what you're asking.
HTH,
- Jeff
[1] http://www.boost.org/doc/libs/1_50_0/libs/mpl/doc/refmanual/set.html [2] http://www.boost.org/doc/libs/1_50_0/doc/html/variant/tutorial.html#variant....