variant pixel buffer to vector using boost::apply_visitor - c++

I am trying to convert variablepixelbuffer.vbuffer() to a vector of double values using apply_visitor in boost.
I came with this piece of code till now :
struct GetVector : public boost::static_visitor<std::vector<double>>
{
//values will be returned in a pair. double is
// used since it can contain the value for any pixel type
typedef std::vector<double> result_type;
template<typename T
void myfunction (const T& i) { // function:
result_type.push_back(static_cast<double>(*i));
}
template<typename T>
result_type
operator() (const T& v)
{
typedef typename T::element_type::value_type value_type;
std::for_each (v->data(), v->data() + v->num_elements(), myfunction);
return result_type;
}
};
/* pixel-example-start */
void
readPixelData(const FormatReader& reader,
std::ostream& stream,int x,int y,int w,int h)
{
// Change the current series to this index
reader.setSeries(0);
// Get total number of planes (for this image index)
dimension_size_type pc = reader.getImageCount();
// Pixel buffer
VariantPixelBuffer buf;
dimension_size_type xd = x;
dimension_size_type yd = y;
dimension_size_type wd = w;
dimension_size_type hd = h;
// Loop over planes (for this image index)
for (dimension_size_type p = 0 ; p < pc; p++)
{
// Read the entire plane into the pixel buffer.
reader.openBytes(p, buf,xd,yd,wd,hd);
}
GetVector visitor;
GetVector::result_type result = boost::apply_visitor(visitor, buf.vbuffer());
}
But i am getting some long errors, and some piece of it are
/usr/include/boost/variant/detail/apply_visitor_unary.hpp:60:43:
required from ‘typename Visitor::result_type
boost::apply_visitor(Visitor&, Visitable&) [with Visitor =
MinMaxVisitor; Visitable =
boost::variant >,
boost::mpl::v_item >,
boost::mpl::v_item
, boost::mpl::v_item >,
boost::mpl::v_item >,
boost::mpl::v_item >,
boost::mpl::v_item
, boost::mpl::v_item
, boost::mpl::v_item
, boost::mpl::v_item
, boost::mpl::v_item
, boost::mpl::vector0, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1> >, 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_,
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_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_>;
typename Visitor::result_type = std::vector >]’ read_subimage.C:82:85: required from here
/usr/include/c++/4.8/bits/stl_algo.h:4417:14: error: must use ‘.’ or
‘->’ to call pointer-to-member function in ‘__f (...)’, e.g. ‘(...
->* __f) (...)’
How can i reslove this, I need to get the pixel buffer data into vector .

Related

deal with boost variant and boost function

I would like a vector to hold differents kind of boost::function, so, I tried a variant :
#include <boost/variant.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <vector>
void a(int, int)
{}
void b()
{}
int main(int argc, char **argv)
{
typedef boost::variant<boost::function0<void>, boost::function2<void, int, int>> v;
std::vector<v> c;
c.push_back(boost::bind(&a, _1, _2));
c.push_back(boost::bind(&b));
auto& function = boost::get<boost::function2<void, int, int>>(c[0]);
function(4, 5);
}
But I've this error :
/usr/local/include/boost/variant/variant.hpp:1515:28: error: call to member function 'initialize' is ambiguous
initializer::initialize(
~~~~~~~~~~~~~^~~~~~~~~~
/usr/local/include/boost/variant/variant.hpp:1692:9: note: in instantiation of function template specialization 'boost::variant<boost::function0<void>, boost::function2<void, int, int>, 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_, boost::detail::variant::void_>::convert_construct<boost::_bi::bind_t<void, void (*)(int, int), boost::_bi::list2<boost::arg<1>, boost::arg<2> > > >' requested here
convert_construct( detail::variant::move(operand), 1L);
^
I didn't find any help to deal with theses error
(and other compiler output)
https://ideone.com/QEdlyF
Thanks !
The constructor for Boost Function is pretty liberal in what it can accept. This results in there being no "best" constructor amongst the elements types of the variant.
You'll have to explicitly cast.
Then again, it's probably even easier to just hide the knowledge about types alltogether (since the helpful parts are ambiguous anyways) and use Boost Any.

Using boost::make_recursive_variant with tuple

boost::make_recursive_variant is intended to make variants which are recursive, without requiring the creation of an intermediate type by using the tag type boost::recursive_variant_. For std::vector<recursive_variant_> this appears to work fine, however for a std::tuple<int, recursive_variant_> it fails.
Example:
#include <type_traits>
#include <tuple>
#include <vector>
#include <boost/variant.hpp>
using std::cout;
using std::vector;
using std::tuple;
using boost::variant;
using boost::static_visitor;
using boost::apply_visitor;
using boost::make_recursive_variant;
using boost::recursive_variant_;
using A = typename make_recursive_variant<
int,
vector<recursive_variant_>
>::type;
using B = vector<A>;
using C = typename make_recursive_variant<
int,
tuple<int, recursive_variant_>
>::type;
using D = tuple<int, C>;
int main(int, char**)
{
A a = 0;
B b{1, 2};
a = b;
C c = 0;
D d{0, 1};
//c = d;
}
If the last line is uncommented, the program no longer compiles. Is this a usage error (and if yes, how so?), or is it bug or limitation in boost::tuple?
Error message (on mingw-w64 with gcc 4.8.1):
In file included from D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant.hpp:17:0,
from D:\projects\test\main.cpp:4:
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/variant.hpp: In instantiation of 'void boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::convert_construct(T&, int, mpl_::false_) [with T = const std::tuple<int, boost::variant<boost::detail::variant::recursive_flag<int>, std::tuple<int, boost::recursive_variant_>, 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_, boost::detail::variant::void_> >; T0_ = boost::detail::variant::recursive_flag<int>; T1 = std::tuple<int, boost::recursive_variant_>; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_; mpl_::false_ = mpl_::bool_<false>]':
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/variant.hpp:1703:38: required from 'boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::variant(const T&) [with T = std::tuple<int, boost::variant<boost::detail::variant::recursive_flag<int>, std::tuple<int, boost::recursive_variant_>, 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_, boost::detail::variant::void_> >; T0_ = boost::detail::variant::recursive_flag<int>; T1 = std::tuple<int, boost::recursive_variant_>; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_]'
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/variant.hpp:2129:29: required from 'void boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::assign(const T&) [with T = std::tuple<int, boost::variant<boost::detail::variant::recursive_flag<int>, std::tuple<int, boost::recursive_variant_>, 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_, boost::detail::variant::void_> >; T0_ = boost::detail::variant::recursive_flag<int>; T1 = std::tuple<int, boost::recursive_variant_>; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_]'
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/variant.hpp:2168:19: required from 'boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>& boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::operator=(const T&) [with T = std::tuple<int, boost::variant<boost::detail::variant::recursive_flag<int>, std::tuple<int, boost::recursive_variant_>, 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_, boost::detail::variant::void_> >; T0_ = boost::detail::variant::recursive_flag<int>; T1 = std::tuple<int, boost::recursive_variant_>; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_]'
D:\projects\test\main.cpp:37:4: required from here
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/variant.hpp:1557:17: error: no matching function for call to 'boost::variant<boost::detail::variant::recursive_flag<int>, std::tuple<int, boost::recursive_variant_>, 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_, boost::detail::variant::void_>::initializer::initialize(void*, const std::tuple<int, boost::variant<boost::detail::variant::recursive_flag<int>, std::tuple<int, boost::recursive_variant_>, 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_, boost::detail::variant::void_> >&)'
)
^
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/variant.hpp:1557:17: note: candidates are:
In file included from D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/variant.hpp:31:0,
from D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant.hpp:17,
from D:\projects\test\main.cpp:4:
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/detail/initializer.hpp:104:24: note: static int boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::initialize(void*, boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param_T) [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::l_item<mpl_::long_<2l>, int, boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> > > >::initializer_node, mpl_::int_<1> >; Iterator = boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> >; boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param_T = const std::tuple<int, boost::recursive_variant_>&]
static int initialize(void* dest, param_T operand)
^
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/detail/initializer.hpp:104:24: note: no known conversion for argument 2 from 'const std::tuple<int, boost::variant<boost::detail::variant::recursive_flag<int>, std::tuple<int, boost::recursive_variant_>, 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_, boost::detail::variant::void_> >' to 'boost::detail::variant::make_initializer_node::apply<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::l_item<mpl_::long_<2l>, int, boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> > > >::initializer_node, mpl_::int_<1> >, boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> > >::initializer_node::param_T {aka const std::tuple<int, boost::recursive_variant_>&}'
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/detail/initializer.hpp:115:24: note: static int boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::initialize(void*, boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param2_T) [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::l_item<mpl_::long_<2l>, int, boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> > > >::initializer_node, mpl_::int_<1> >; Iterator = boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> >; boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param2_T = std::tuple<int, boost::recursive_variant_>&&]
static int initialize(void* dest, param2_T operand)
^
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/detail/initializer.hpp:115:24: note: no known conversion for argument 2 from 'const std::tuple<int, boost::variant<boost::detail::variant::recursive_flag<int>, std::tuple<int, boost::recursive_variant_>, 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_, boost::detail::variant::void_> >' to 'boost::detail::variant::make_initializer_node::apply<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::l_item<mpl_::long_<2l>, int, boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> > > >::initializer_node, mpl_::int_<1> >, boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> > >::initializer_node::param2_T {aka std::tuple<int, boost::recursive_variant_>&&}'
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/detail/initializer.hpp:149:17: note: static void boost::detail::variant::initializer_root::initialize()
static void initialize();
^
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/detail/initializer.hpp:149:17: note: candidate expects 0 arguments, 2 provided
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/detail/initializer.hpp:115:24: note: static int boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::initialize(void*, boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param2_T) [with BaseIndexPair = boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >; Iterator = boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<2l>, int, boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> > >; boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param2_T = int&&]
static int initialize(void* dest, param2_T operand)
^
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/detail/initializer.hpp:115:24: note: no known conversion for argument 2 from 'const std::tuple<int, boost::variant<boost::detail::variant::recursive_flag<int>, std::tuple<int, boost::recursive_variant_>, 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_, boost::detail::variant::void_> >' to 'boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >, boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<2l>, int, boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> > > >::initializer_node::param2_T {aka int&&}'
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/detail/initializer.hpp:104:24: note: static int boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::initialize(void*, boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param_T) [with BaseIndexPair = boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >; Iterator = boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<2l>, int, boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> > >; boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param_T = const int&]
static int initialize(void* dest, param_T operand)
^
D:/libs/3rdparty-prebuild-vc11-win64/vc11/win64/boost-1_54_0-vc11-win64/include/boost-1_54/boost/variant/detail/initializer.hpp:104:24: note: no known conversion for argument 2 from 'const std::tuple<int, boost::variant<boost::detail::variant::recursive_flag<int>, std::tuple<int, boost::recursive_variant_>, 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_, boost::detail::variant::void_> >' to 'boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >, boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<2l>, int, boost::mpl::l_item<mpl_::long_<1l>, std::tuple<int, boost::recursive_variant_>, boost::mpl::l_end> > > >::initializer_node::param_T {aka const int&}'
The problem is that make_recursive_variant isn't aware of variadic templates, so it doesn't know to expand recursive_variant_ within std::tuple<..., recursive_variant_>.
You can test this by changing std::tuple to std::pair (a fixed-adic template) and observing that that works fine.
As a workaround, you can teach Boost.Variant how to expand within variadic templates with the following snippet (place at the top level of your source file):
namespace boost { namespace detail { namespace variant {
template<template<typename...> class F, typename... Ts, typename Dest, typename Source>
struct substitute<
F<Ts...>
, Dest
, Source
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>)
>
{
typedef F<typename substitute<
Ts, Dest, Source
>::type...> type;
};
}}} // namespace boost::detail::variant
Edit: I've put in a pull request: https://github.com/boostorg/variant/pull/2

How to use Boost Spirit with variant with more than 20 types?

I'm parsing a quite complex grammar with Boost Spirit and I'm facing a problem with a variant that have more than 20 types (21 here):
namespace eddic { namespace ast {
typedef boost::mpl::vector<
Integer,
IntegerSuffix,
Float,
Litteral,
VariableValue,
DereferenceValue,
Expression,
Unary,
Null,
True,
False,
ArrayValue,
FunctionCall,
MemberFunctionCall,
Cast,
BuiltinOperator,
Assignment,
SuffixOperation,
PrefixOperation,
Ternary
> types_initial;
typedef boost::mpl::push_back<types_initial, New>::type types;
typedef boost::make_variant_over<types>::type Value;
}}
Boost Spirit does not recognize the last type (eddic::ast::New) added with push_back. When I parse something that have this element, it fails with this error:
eddic: /usr/include/boost/variant/detail/visitation_impl.hpp:264:
typename Visitor::result_type
boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV,
mpl_::false_, NoBackupFlag, Which*, step0*) [with Which =
mpl_::int_<0>; step0 =
boost::detail::variant::visitation_impl_step,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>,
0>, 0>, 0>, 0>, 0l>,
boost::mpl::v_iter,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>,
0>, 0>, 0>, 0>, 21l> >; Visitor =
boost::variant, boost::mpl::vector,
eddic::ast::Deferred,
eddic::ast::Deferred, eddic::ast::Null,
eddic::ast::True, eddic::ast::False,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred >, 0> >,
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_, boost::detail::variant::void_,
boost::detail::variant::void_>::assigner; VoidPtrCV = const void*;
NoBackupFlag =
boost::variant, boost::mpl::vector,
eddic::ast::Deferred,
eddic::ast::Deferred, eddic::ast::Null,
eddic::ast::True, eddic::ast::False,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred >, 0> >,
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_, boost::detail::variant::void_,
boost::detail::variant::void_>::has_fallback_type_; typename
Visitor::result_type = void; mpl_::false_ = mpl_::bool_]:
Assertion `!"Boost.Variant internal error: 'which' out of range."'
failed.
If I swap two elements (Ternary and New for example), New is correctly recognized, but not Ternary. It is only the last element that fails.
I already tried using push_front or vector21, but it doesn't change anything, it's always the last element that have problem. In my opinion it comes from the fact that Spirit uses a variant internally before copying it to my variant_over type.
Is there a workaround to this problem ?
I could probably reduce the number to 20, but the problem is that I will certainly have more than that in the future.
Thanks a lot for any idea
Define BOOST_MPL_LIMIT_VECTOR_SIZE to whatever new limit you want, but going this high is usually a hint at design problems so it might be worth to give it some consideration.

boost::variant linker error with gcc

I am going a bit nuts trying to figure out why the following won't compile:
#include <iostream>
#include <array>
#include <boost/variant.hpp>
#include <forward_list>
typedef unsigned long long very_long;
typedef boost::variant< int, std::string > variants_type;
typedef std::array< variants_type, 5 > row_type;
typedef std::forward_list<row_type> rows_holder_type;
int main() {
rows_holder_type rows;
row_type row_data;
row_data[0] = 0;
row_data[1] = 0;
row_data[2] = 0;
row_data[3] = 0;
row_data[4] = 0;
rows.push_front(row_data);
}
This is the compiler error I am getting:
/usr/include/testing/test_code.o||In function 'std::array<boost::variant<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 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_, boost::detail::variant::void_>, 5ul>::array(std::array<boost::variant<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 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_, boost::detail::variant::void_>, 5ul> const&)':|
store.cpp:(.text._ZNSt5arrayIN5boost7variantIiSsNS0_6detail7variant5void_ES4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_EELm5EEC2ERKS6_[_ZNSt5arrayIN5boost7variantIiSsNS0_6detail7variant5void_ES4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_EELm5EEC5ERKS6_]+0x31)||undefined reference to 'boost::variant<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 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_, boost::detail::variant::void_>::variant(boost::variant<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 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_, boost::detail::variant::void_> const&)'|
||=== Build finished: 1 errors, 0 warnings ===|
If I replace:
typedef boost::variant< int, std::string > variants_type;
with:
typedef boost::any variants_type;
The code compiles, but I do not want to use boost::any for performance reasons.
I tested your code with MSVC and gcc 4.7.0. MSVC compiles and links the code fine (of course with #include <string>), but gcc gives a linker error on the last line rows.push_front(row_data);. If you comment that line out, gcc accepts the code. I see no reason why gcc gives a linker error and am concluding that it is a bug with gcc. One workaround on gcc would be to change std::array to std::vector.
(From the error message I assume you are using Code::Blocks with gcc)
I've eliminated extra code and the following example still gives the linker error:
#include <boost/variant.hpp>
#include <array>
int main()
{
std::array<boost::variant<int, double>, 5> row_type1;
std::array<boost::variant<int, double>, 5> row_type2 = row_type1;
}
You're missing #include <string>; other than that your code is fine.

boost::variant and printing methods of elements in vector

std::vector< boost::variant<std::string, int> > vec;
std::string s1("abacus");
int i1 = 42;
vec.push_back(s1);
vec.push_back(i1);
std::cout << vec.at(0).size() << "\n";
when I try to run this code, I get the following error:
main.cpp:68: error: ‘class boost::variant<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, 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_, boost::detail::variant::void_>’ has no member named ‘size’
make: *** [main.o] Error 1
however, being a string it should have a size() method. I'm not sure what is going wrong. note that replacing the last line with:
std::cout << vec.at(0) << "\n";
will print "abacus", as expected.
being a string it should have a size() method
It’s not a string – it’s a variant. You first need to tell the compiler that you know there’s a string inside – i.e. retrieve it using boost::get<std::string>(vec[0]).
Be sure to read the Boost.Variant tutorial.
You need to get the first type of this variant (which is the string), the class boost::variant which you are accessing with vector::at() has no method called size(), try something like::
boost::get<0>(vec.at(0)).size(); // I think that's the syntax....