Boost logo

Boost Users :

Subject: [Boost-users] [variant] GNU MP Bignum (gmp) compatibility
From: Sven Heithecker (sven.heithecker_at_[hidden])
Date: 2010-08-08 12:48:18


Hello !

The following code compiles correctly and does what I
want:

#include <iostream>
#include <string>
#include
<boost/variant.hpp>
#include <gmpxx.h>

using namespace std;

typedef
boost::variant<int,string> var_t; // COMMENT
//typedef
boost::variant<mpz_class,mpq_class> var_t; // UNCOMMENT

class add : public
boost::static_visitor<var_t>
 {
  public:
  template<typename T>
    var_t
operator()(const T &op1, const T &op2) const
   {
    return(op1+op2);
   }

 template<typename T1, typename T2>
    var_t operator()(const T1 &op1,
const T2 &op2) const
   {
    throw; // just for demonstration
   }
 };

int
main()
 {
  var_t v0(2);
  var_t v1(3);
  var_t r0 =
apply_visitor(add(),v0,v1);
  cout << r0 << endl; //
"5"

  var_t v10("Hello, ");
  var_t v11("World !");
  var_t r10 =
apply_visitor(add(),v10,v11);
  cout << r10 << endl; //
"Hello, World !"

  var_t error= apply_visitor(add(),v0,v10); // try to add
"2" and "Hello, "
  cout << error << endl; // never
executed
 }

However, if I change to the "gmp" Variant typedef indicated
above, compilation fails with an error in the boost::variant sources. I
tried to extract the core error
message:

[...]
/usr/include/boost/variant/variant.hpp:1293: error: call of
overloaded ‘initialize(void*, const char [8])’ is
ambiguous
/usr/include/boost/variant/detail/initializer.hpp:89: note:
candidates are: static int
boost::detail::variant::make_initializer_node::apply<BaseIndexPair,
Iterator>::initializer_node::initialize(void*, typename
boost::call_traits<typename boost::unwrap_recursive<typename
boost::mpl::deref<Iterator>::type>::type>::param_type) [with BaseIndexPair =
boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost:
:mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >,
boost::mpl::l_iter<boost::mpl::list2<__gmp_expr<__mpz_struct [1],
__mpz_struct [1]>, __gmp_expr<__mpq_struct [1], __mpq_struct [1]> > >
>::initializer_node, mpl_::int_<1> >, Iterator =
boost::mpl::l_iter<boost::mpl::list1<__gmp_expr<__mpq_struct [1],
__mpq_struct [1]> > >] <near
match>
/usr/include/boost/variant/detail/initializer.hpp:89: note:
      static int
boost::detail::variant::make_initializer_node::apply<BaseIndexPair,
Iterator>::initializer_node::initialize(void*, typename
boost::call_traits<typename boost::unwrap_recursive<typename
boost::mpl::deref<Iterator>::type>::type>::param_type) [with BaseIndexPair =
boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >,
Iterator = boost::mpl::l_iter<boost::mpl::list2<__gmp_expr<__mpz_struct [1],
__mpz_struct [1]>, __gmp_expr<__mpq_struct [1], __mpq_struct [1]> > >] <near
match>
[...]

After having a look at the gmp documentation, especially the
"12.6 C++ Interface Limitations" chapter, I think this has something to do
with the various conversion functions between the gmp classes and the way
how the gmp classes are implemented.

Is there any (easy?) way to make
boost::variant and gmp compatible ?

Regards, Sven

-- 
Sven Heithecker
GPG
Fingerprint: 527F 06C2 BF51 96CE DFF7 CC89 1A6B DFD5 BEC2 02A6

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net