2014-12-20 2 views
6

Я пытаюсь предоставить программе способ добавления новых объектов к варианту в библиотеке, но я сталкиваюсь с некоторыми загадочными ошибками.Расширение варианта boost с помощью списка MPL

#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; 
} 

С помощью mpl::joint_view (который я предполагаю, если наиболее эффективный способ достижения этой цели), я получаю следующее сообщение об ошибке:

/usr/local/include/boost/mpl/clear.hpp:29:7: error: implicit instantiation of undefined template 

раскомментировать другую попытку, используя mpl::copy, и заменить его с оригиналом, то изменения ошибки:

/usr/local/include/boost/mpl/aux_/push_back_impl.hpp:40:9: error: no matching function for call to 'assertion_failed' 

Что, интересно, имеет 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. 

Ни одна из этих ошибок имеет никакого смысла для меня, как, ж/г/т первым, я не вижу, какие шаблоны не являются полными и для второго, который push_back специализации я не использую?

+1

Второй один довольно легко понять, [ ' mpl :: list'] (http://www.boost.org/libs/mpl/doc/refmanual/list.html) не может использоваться с 'push_back'. Вы можете использовать 'boost :: mpl :: front_inserter ' или просто использовать 'mpl :: vector' в типе typedef' Types'. – llonesmiz

+0

Аааа, да, вот и все. Благодаря! Я оставил вопрос открытым, потому что решение joint_view, вероятно, было лучше или два, чтобы делать это на производстве. –

+0

Я не вижу лучшего способа, если вы не намерены изменять 'make_variant_over'. 'mpl :: copy' from' mpl :: vector 'это способ, если вы спросите меня – sehe

ответ

2

Проблема заключается в том, что boost::mpl::clear<> не реализована для joint_view ... поэтому огромная свалка компилятор оканчивающиеся:

/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> > >' 

(я не знаю, как форматировать, что правильно)

Этот может быть просто недосмотр в библиотеке, или может быть просто неясно , который пустой тип последовательности должен быть возвращен в этом случае. Если вы хотите использовать joint_view, вы должны обеспечить специализацию clear_impl где-то:

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. 
     }; 
    }; 
} } 

С, что ваш код компилируется для меня на обоих НКУ и лязгом.

В качестве альтернативы, если добавлять материал в namespace boost::mpl поражает вас, как немного тенистые, но вы все еще хотите придерживаться list с, вы можете просто использовать insert_range:

typename boost::make_variant_over< 
    typename boost::mpl::insert_range< 
     Types, 
     typename boost::mpl::end<Types>::type, 
     LocalTypes 
    >::type 
>::type container_; 
+0

Это, кажется, спасибо! Я предполагаю, что, принимая это в контексте, 'mpl :: copy' и' mpl :: vector' действительно звучат как лучший выбор. Как вы сказали, пустой 'mpl :: joint_view' на самом деле не имеет никакого смысла ... –

+1

@SamKellett На самом деле может использовать тот же метафайл' insert_range' с 'vector'. В любом случае, у вас получается то же самое. – Barry