I'm trying to provide a program a way to add new objects to a variant in a library but I'm encountering some cryptic errors.
#include <boost/mpl/copy.hpp>
#include <boost/mpl/joint_view.hpp>
#include <boost/mpl/list.hpp>
#include <boost/variant/variant.hpp>
struct InternalType1 {};
struct InternalType2 {};
template <typename LocalTypes>
struct Foo
{
typedef boost::mpl::list<
InternalType1,
InternalType2
> Types;
typename boost::make_variant_over<
typename boost::mpl::joint_view<
Types,
LocalTypes
>::type
>::type container_;
// typename boost::make_variant_over<
// typename boost::mpl::copy<
// LocalTypes,
// boost::mpl::back_inserter<Types>
// >::type
// >::type container_;
};
struct LocalType1 {};
struct LocalType2 {};
int main()
{
typedef boost::mpl::list<
LocalType1,
LocalType2
> Types;
Foo<Types> foo;
}
By using a mpl::joint_view
(which I assume if the most efficient way of achieving this), I get the following error:
/usr/local/include/boost/mpl/clear.hpp:29:7: error: implicit instantiation of undefined template
By uncommenting the other attempt, using mpl::copy
, and replacing it with the original, then the error changes:
/usr/local/include/boost/mpl/aux_/push_back_impl.hpp:40:9: error: no matching function for call to 'assertion_failed'
Which, interestingly, has the following comment:
// should be instantiated only in the context of 'has_push_back_impl';
// if you've got an assert here, you are requesting a 'push_back'
// specialization that doesn't exist.
Neither of these errors make any sense to me as, w/r/t the first, I don't see which templates are not complete and for the second, which push_back specialization I'm not using?
The problem is that boost::mpl::clear<>
is not implemented for a joint_view
... hence the huge compiler dump terminating with:
/usr/local/include/boost/mpl/clear.hpp:29:7: error: implicit instantiation of undefined template 'boost::mpl::clear_impl<boost::mpl::aux::joint_view_tag>::apply<boost::mpl::joint_view<boost::mpl::list<InternalType1, InternalType2, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::list<LocalType1, LocalType2, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> > >'
(I don't know how to format that properly)
This could be just an oversight in the library, or it may just not be clear which empty Sequence type should be returned in this case. If you want to use a joint_view
, you'll have to provide a specialization of clear_impl
somewhere:
namespace boost { namespace mpl {
template <>
struct clear_impl<aux::joint_view_tag>
{
template <typename JV>
struct apply {
typedef list<> type; // since you're using list I figured
// I would too.
};
};
} }
With that, your code compiles for me on both gcc and clang.
Alternatively, if adding stuff into namespace boost::mpl
strikes you as a little shady but you still want to stick with list
s, you can just use insert_range
:
typename boost::make_variant_over<
typename boost::mpl::insert_range<
Types,
typename boost::mpl::end<Types>::type,
LocalTypes
>::type
>::type container_;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With