2014-12-20 13 views
6

Sto provando a fornire un programma per aggiungere nuovi oggetti a una variante in una libreria, ma sto riscontrando alcuni errori criptici.Estensione della variante di boost con un elenco 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; 
} 

Utilizzando un mpl::joint_view (che presumo se il mezzo più efficace per raggiungere questo), ottengo il seguente errore:

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

Rendendo attivi l'altro tentativo, utilizzando mpl::copy, e sostituendola con l'originale, le modifiche di errore:

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

il che, curiosamente, ha la 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. 

Nessuno di questi errori ha alcun senso per me come, w/r/t la prima, non vedo che i modelli non sono stati compilati e per la seconda, che push_back la specializzazione non sto usando?

+1

La seconda è abbastanza facile da capire, [ ' mpl :: list'] (http://www.boost.org/libs/mpl/doc/refmanual/list.html) non può essere usato con 'push_back'. Potresti usare 'boost :: mpl :: front_inserter ' o semplicemente usare un 'mpl :: vector' nel typedef di' Types'. – llonesmiz

+0

Aaaah, sì è così. Grazie! Lascio la domanda aperta perché la soluzione joint_view è probabilmente la migliore o le due da fare in produzione. –

+0

Non vedo un modo migliore a meno che non si intenda modificare 'make_variant_over'. 'mpl :: copy' da' mpl :: vector's è il modo in cui me lo chiedi – sehe

risposta

2

Il problema è che boost::mpl::clear<> non è implementato per un joint_view ... da qui l'enorme discarica compilatore termina con:

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

(non so come formattare che correttamente)

Questo potrebbe essere solo una svista nella libreria, oppure potrebbe non essere chiaro che il tipo di sequenza vuoto deve essere restituito in questo caso. Se si desidera utilizzare un joint_view, dovrete fornire una specializzazione di clear_impl da qualche parte:

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

Con questo, il codice compila per me su entrambi gcc e clang.

In alternativa, se l'aggiunta di roba in namespace boost::mpl ti colpisce come un po 'buia, ma si vuole comunque restare con list s, si può semplicemente utilizzare insert_range:

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

Sembra che sia così, grazie! Immagino, considerando questo nel contesto, un 'mpl :: copy' e' mpl :: vector' sembrano davvero la scelta migliore. Come hai detto tu, un vuoto 'mpl :: joint_view' non ha alcun senso ... –

+1

@SamKellett Può effettivamente usare la stessa metafunzione' insert_range' con 'vector'. Ad ogni modo, finisci con la stessa cosa. – Barry

Problemi correlati