//Purpose: // Test code posted in: /* From: "Petros" Newsgroups: gmane.comp.lib.boost.user Subject: compilation problem and a couple of boost::variant questions Date: Wed, 11 Jul 2012 14:32:17 -0400 Lines: 772 */ // #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{ const size_t i_; subscript_operator( const size_t i ):i_(i){} template double operator()( _v const & v ) const { return v[i_] ; } }; template class VariantT :public variant< _V, _Z, _U > { public: typedef _Z zero_type ; typedef _U unit_type ; typedef VariantT<_V, _Z, _U> self_type ; typedef variant< _V, _Z, _U > variant_type ; template < typename _V> explicit VariantT( _V const & v ) :variant_type(v) {} VariantT() {} VariantT( self_type const & v ) :variant_type(static_cast(v)) {} template < typename _V> VariantT & operator = ( _V const & v ) { *static_cast(this) = static_cast(v); return(*this); } VariantT & operator = ( self_type const & v ) { *static_cast(this) = v; return(*this); } double operator[]( const size_t i ) const { boost::apply_visitor( subscript_operator(i) , *this ) ; } bool isZero() const { return which() == 1 ; } bool isUnit() const { return which() == 2 ; } private: }; template < typename _V1, typename _V2 > class MultVarVar{ public: MultVarVar( _V1 const & v1, _V2 const & v2 ) :v1_(v1),v2_(v2) {} ~MultVarVar() {} typedef typename _V1::zero_type zero_type ; typedef typename _V1::unit_type unit_type ; double operator[]( const size_t i ) const { return boost::apply_visitor ( elementwise_visitor( i ), v1, v2 ) ; } private: _V1 const & v1_ ; _V2 const & v2_ ; struct elementwise_visitor : public boost::static_visitor< double > { const size_t & i_; public: elementwise_visitor( const size_t & i ) :i_(i) {} template double operator()( _V1 const & v1, _V2 const & v2) const { return v1[i_] * v2[i_] ; } }; }; template < typename _V1, typename _V2 > class MultVarVarResult :public variant, typename MultVarVar<_V1,_V2>::zero_type, typename MultVarVar<_V1,_V2>::unit_type, _V1, _V2 > { public: typedef variant< typename MultVarVar<_V1, _V2 > , typename MultVarVar<_V1,_V2>::zero_type, typename MultVarVar<_V1,_V2>::unit_type, _V1, _V2 > variant_type; typedef MultVarVarResult<_V1, _V2> self_type ; typedef typename _V1::zero_type zero_type ; typedef typename _V1::unit_type unit_type ; template /*explicit*/ MultVarVarResult( _V const & v ) :variant_type(v) {} MultVarVarResult( self_type const & v ) :variant_type(static_cast(v)) {} template < typename _V> MultVarVarResult & operator = ( _V const & v ) { *static_cast(this) = static_cast(v); return(*this); } MultVarVarResult & operator = ( self_type const & v ) { *static_cast(this) = v; return(*this); } double operator[]( const size_t i ) const { boost::apply_visitor( subscript_operator(i), *this ) ; } private: }; template MultVarVarResult<_V1, _V2> operator * ( _V1 const & v1, _V2 const & v2 ) { if ( v1.isZero() || v2.isZero() ) return MultVarVarResult<_V1, _V2>( typename MultVarVar<_V1,_V2>::zero_type() ) ; if ( v1.isUnit() ) return MultVarVarResult<_V1, _V2>( v2 ); if ( v2.isUnit() ) return v1 ; else return MultVarVarResult<_V1, _V2>( MultVarVar<_V1, _V2>( v1, v2 ) ) ; } typedef VariantT< Vector1, Zero1, One1 > Variant1; typedef VariantT< Vector2, Zero2, One2 > Variant2; int main(){ Variant1 v1; v1 = Zero1() ; Variant2 v2; v2 = One2() ; auto x = v1 * v2 ; return x[0] == double(0) ; }