2

I have the following error message:

/usr/include/boost/variant/detail/visitation_impl.hpp:207: typename Visitor::result_type boost::detail::variant::visitation_impl(int, int, Visitor &, VPCV, mpl::true_, NBF, W *, S *) [W = mpl_::int_<20>, S = boost::detail::variant::visitation_impl_step<boost::mpl::l_iter<boost::mpl::l_end>, boost::mpl::l_iter<boost::mpl::l_end> >, Visitor = boost::detail::variant::copy_into, VPCV = const void *, NBF = boost::variant<TypeInfo, 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_fallback_type_]: Assertion `false' failed.

This happens when I am passing std::vector<A> as a parameter by value to some function and A is defined as using A = boost::variant<B, int>;. To be simple, B is defined like this:

class B
{
    Data data;
    std::vector< boost::variant<std::shared_ptr<C>, B> > vec;
};

B is TypeInfo in error message.

void func(std::vector<B> vec); //signature

auto result = func(that_vector_with_variants); //that line causes an error

I have found similar bug here https://svn.boost.org/trac/boost/ticket/5146

My question is: Is it a bug in boost? How can I make my code work?

Update:

I think that I have to add that if I change std::vector<boost::variant<std::shared_ptr<C>, B> > vec; to std::vector<boost::variant<C*, B> > vec; then everything works.

justanothercoder
  • 1,830
  • 1
  • 16
  • 27
  • What is the visitor? You don't show any related code. You're using a variant. In a container. Good. That's basically all we know for now – sehe Jan 16 '15 at 09:12
  • @sehe, It is the main problem, that it is some internal visitor. When I look backtrace in gdb, I see that error appeared during copying vector. – justanothercoder Jan 16 '15 at 09:21

1 Answers1

3

Going out on a limb, and from reading that bug report, you maybe inadvertantly doing something like this:

#include <iostream>
#include <boost/make_shared.hpp>
#include <boost/variant.hpp>

using P = boost::shared_ptr<int>;
using V = boost::variant<P, int>;
using C = std::vector<V>;

int main() {
    P p = boost::make_shared<int>(42);
    assert(p.unique());

    C v = { p };
    assert(!p.unique());

    v = std::move(v);
    assert(!p.unique()); // WHOOPS assert fails
}

Of course this sample is contrived², because I don't know your actual code/use case.

The last assert fails. This is due to the fact that the order of the operations, internally, is such that the original variant is cleared (and the contained value destructed) before the new value is assigned:

"Never-Empty" Guarantee

While the never-empty guarantee might at first seem "obvious," it is in fact not even straightforward how to implement it in general

Cf. The "Ideal" Solution: False Hopes from Boost Variant "Design Overview"

So, had we not had a "reference" to the int in p, this operation would have destroyed the instance before it was reassigned.

In this case, it looks more like a pattern of use (essentially in-place modification with smart pointers ¹) to avoid. In this particular case, these appear to work (on my compiler/library implementation):

std::move(v.begin(), v.end(), v.begin());
// or
std::copy(std::make_move_iterator(v.begin()), std::make_move_iterator(v.end()), v.begin());
// or
v.assign(std::make_move_iterator(v.begin()), std::make_move_iterator(v.end()));

But I'd certainly prefer to write it more like

C tmp = std::move(v); 
v = std::move(tmp);

Just because there are no guarantees otherwise.


¹ always a hazard! Even Scott Meyers feel for this in his "More Effective C++", see the erratum p.200/202

² related: What does the standard library guarantee about self move assignment?

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633