2013-04-04 11 views
6

Come si ereditano i costruttori da una classe base del modello senza ripetere gli argomenti di template (e senza l'utilizzo di macro):Costruisce ereditari dalla classe base del modello senza ripetere gli argomenti del modello?

Ad esempio, questa non funziona (usando GCC 4.8):

template <typename T> 
struct base {}; 

template <typename U> 
struct derived : base<U> { 
    using base::base; 
}; 

Lo fa lavorare se ripeto le argomentazioni di modello della classe base:

template <typename T> 
struct base {}; 

template <typename U> 
struct derived : base<U> { 
    using base<U>::base; 
}; 

il problema è che "U" potrebbe essere qualcosa di molto complesso e che è fastidioso e soggetto a errori di ripetere. Ad esempio, ecco uno dei miei esempi motivanti originali:

#include <boost/multi_index_container.hpp> 
#include <boost/multi_index/key_extractors.hpp> 
#include <boost/multi_index/ordered_index.hpp> 
#include <boost/multi_index/sequenced_index.hpp> 

using namespace boost::multi_index; 

struct as_list_tag {}; 
struct as_set_tag {}; 

template <typename T> 
struct unique_list : multi_index_container < 
    T, 
    indexed_by < 
     sequenced<tag<as_list_tag>>, 
     ordered_unique<tag<as_set_tag>, identity<T>> 
    > 
> { 
    using multi_index_container < 
     T, 
     indexed_by < 
      sequenced<tag<as_list_tag>>, 
      ordered_unique<tag<as_set_tag>, identity<T>> 
     > 
    > 
    ::multi_index_container; 
    using as_list = as_list_tag; 
    using as_set = as_set_tag ; 
}; 

ho finito per lavorare intorno a questo utilizzando una macro:

#define MAKE_UNIQUE_LIST(template_params...)\ 
template <typename T>\ 
struct unique_list : multi_index_container template_params\ 
{\ 
    using multi_index_container template_params ::multi_index_container;\ 
    using as_list = as_list_tag;\ 
    using as_set = as_set_tag ;\ 
}; 

MAKE_UNIQUE_LIST(< 
    T, 
    indexed_by < 
     sequenced<tag<as_list_tag>>, 
     ordered_unique<tag<as_set_tag>, identity<T>> 
    > 
>) 
#undef MAKE_UNIQUE_LIST 

Esiste un modo migliore per avvicinarsi a questo? Qualche trucco di sintassi che mi manca? =)

+0

'typedef base parent;' –

+0

@MooingDuck Devi ancora ripeterlo almeno due volte (una volta in derivazione e una volta in 'using' per ereditare i costruttori). – Zereges

risposta

3

Non è perfetto, ma si potrebbe avere una classe che genera il tipo:

template <typename T> 
struct unique_list_base { 
    typedef multi_index_container < 
     T, 
     indexed_by < 
      sequenced<tag<as_list_tag>>, 
      ordered_unique<tag<as_set_tag>, identity<T>> 
     > 
    > type; 
}; 

template <typename T> 
struct unique_list : unique_list_base<T>::type { 
    using unique_list_base<T>::type::multi_index_container; 
    using as_list = as_list_tag; 
    using as_set = as_set_tag ; 
}; 
+0

Informazioni sul typename prima della unique_list_base :: type GCC dice: 'keyword 'typename' non è consentito in questo contesto (la classe base è implicitamente un tipo)' – wjl

+0

Dopo aver rimosso il typename in più e aver corretto I typo dove mi stavo confondendo, Sono stato in grado di fare questo lavoro. Grazie! – wjl

+4

@wjl È possibile semplificare ulteriormente utilizzando 'modello utilizzando unique_list_base = multi_index_container <...>;'. –

2

Proprio per evidenziare soluzione Daniel Frey dal momento che non ha preso la briga di fare una risposta completa: modello utilizzando dichiarazione (aka template typedef) è la strada da percorrere.

template <typename T> 
using unique_list_base = 
    multi_index_container < 
     T, 
     indexed_by < 
      sequenced<tag<as_list_tag>>, 
      ordered_unique<tag<as_set_tag>, identity<T>> 
     > 
    >; 

template <typename T> 
struct unique_list : unique_list_base<T> { 
    using unique_list_base<T>::multi_index_container; 
    using as_list = as_list_tag; 
    using as_set = as_set_tag ; 
}; 

In questo modo, è possibile liberarsi della struct e tutto il boilerplate associati che sono stati ampiamente utilizzato con il linguaggio C++ 03 foobar<T>::type.

+0

Bello. Recentemente ho usato 'using' molto e vedo che è utile ancora qui! =) – wjl

+0

Ancora meglio, questo mi permette di cambiare la linea del costruttore ereditato in "using unique_list_base :: unique_list_base;" che è più comprensibile. – wjl

2

Facile:

template <typename U, typename thebase=base<U>> 
struct derived : thebase { 
    using thebase::thebase; 
}; 

Il rovescio della medaglia è che cambia l'interfaccia esterna del modello di avere due argomenti template. È possibile risolvere che in questo modo:

template <typename U, typename thebase=base<U>> 
struct derived_impl : thebase { 
    using thebase::thebase; 
}; 
template<typename U> 
using derived = derived_impl<U>; 
0

In realtà, sembra che MSVC, al contrario di gcc, non richiede nemmeno di ripetere l'argomento del modello: si potrebbe basta scrivere "utilizzando di base :: base".

Problemi correlati