Boost logo

Boost :

From: craig perras (craigp98072_at_[hidden])
Date: 2004-06-30 13:57:37


Hello -

I want to do type conversions (checked at
compile-time) using boost::variant. So I naively
made a 'convert' visitor, which has designed to
(hopefully) safely convert the variant value to
another type (eg: a client might try to assign the
variant's int value to an unsigned short).

For instance:

typedef boost::variant < std::string, int, double >
ParamValue;

// ----- ConvertParamValueVisitor

//T is the type which will be assigned the variant's
value
//V is the Variant/Visitor
template<typename T>
struct ConvertParamValueVisitor<T>
{
  typedef ConvertParamValueVisitor self;
  typedef void result_type;

  self( T*& val ) : value_(val) {}

  template<typename V>
  result_type operator()( const V& v, typename
boost::enable_if<TypeTraits::is_arithmetic<V> >::type*
dummy = 0 ) const
  {
    *value_ = boost::numeric_cast<T>(v);
  }

  template<typename V>
  result_type operator()( const V& v, typename
boost::enable_if<TypeTraits::is_string<V> >::type*
dummy = 0 ) const
  {
    *value_ = v;
  }

private:
  T*& value_;
};

It seems boost::variant will instantiate all members
for all variant types, even the ones I try to suppress
using enable_if. To work around this, I've tried
various things, like specializing
ConvertParamValueVisitor based on T, using
lazy_enable_if, etc. Here's one attempt:

  // ----- ConvertParamValueVisitor

  //T is the type which will be assigned the variant's
value
  //V is the Variant/Visitor

  //not implemented
  template<typename T, class Enable = void>
  struct ConvertParamValueVisitor;

  //ConvertParamValueVisitor int, double: use numeric
cast
  template<typename T>
  struct ConvertParamValueVisitor<T, typename
boost::enable_if<TypeTraits::is_arithmetic<T> >::type
>
  {
    typedef void result_type;
    typedef ConvertParamValueVisitor self;

    self( T*& val ) : value_(val) {}

    template<typename V>
    result_type operator()( const V& val, typename
boost::enable_if<TypeTraits::is_arithmetic<V> >::type*
dummy = 0 ) const
    {
      *value_ = boost::numeric_cast<T>(val);
    }

    //not implemented
    template<typename V>
    result_type operator()( const V& val, typename
boost::enable_if<TypeTraits::is_string<V> >::type*
dummy = 0 ) const;

  private:
    T*& value_;
  };

  //ConvertParamValueVisitor string
  template<typename T>
  struct ConvertParamValueVisitor<T, typename
boost::enable_if<TypeTraits::is_string<T> >::type >
  {
    typedef void result_type;
    typedef ConvertParamValueVisitor self;

    self( T*& val ) : value_(val) {}

    //not implemented
    template<typename V>
    result_type operator()( const V& val, typename
boost::enable_if<TypeTraits::is_arithmetic<V> >::type*
dummy = 0 ) const;

    template<typename V>
    result_type operator()( const V& val, typename
boost::enable_if<TypeTraits::is_string<V> >::type*
dummy = 0 ) const
    {
      *value_ = val;
    }

  private:
    T*& value_;
  };

Is there any way to get something like this to work?
Am I simply mis-applying boost::variant? I could of
course just throw an exception in the unsupported/not
implemented methods above, but I'd like this checked
at at compile time if possible.

(note that my question is generally applicable to
visitors, not just to boost::variant).

thanks!
--craig

                
__________________________________
Do you Yahoo!?
Yahoo! Mail - 50x more storage than other providers!
http://promotions.yahoo.com/new_mail


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk