2012-12-25 12 views
9

Supponiamo che io voglia applicare la limitazione che il parametro template passato è figlio di Foo.Come applicare la limitazione child-of-X al parametro template?

C'è un modo per far rispettare questo attraverso i caratteri? Un errore static_assert in fase di compilazione sarebbe ottimo.

Nel seguente codice, facciamo una domanda divisa in due parti.

  1. Consente di compilare solo My_Limited_Template<Bar>.
  2. Consentire solo la compilazione di My_Limited_Template<TBar>.

EDIT mi scuso per il cattivo di denominazione: TBar e TBaz sono destinate ad essere le classi non-template su scopi. Ho appena attaccato T davanti ai nomi per disambiguare dalle classi nella parte 1.

CODICE

struct Foo { };    // no 
struct Bar : public Foo { }; // yes 
struct Baz { };    // no 

template< typename T > 
struct TFoo { };      // no 
struct TBar : public TFoo<TBar> { }; // yes 
struct TBaz { };      // no 

template< typename T > 
struct My_Limited_Template 
{ 
    // Part One: 
    // My_Limited_Template<Foo> // disallow 
    // My_Limited_Template<Bar> // allow 
    // My_Limited_Template<Baz> // disallow 
    // 
    // Part Two: 
    // My_Limited_Template<TFoo<int>> // disallow 
    // My_Limited_Template<TBar>  // allow 
    // My_Limited_Template<TBaz>  // disallow 
}; 
+1

Quindi la seconda parte dovrebbe * "consentire solo i parametri derivati ​​da TFoo utilizzando CRTP" *? – jrok

+0

@jrok +1 se potessi coinvolgere CRTP, sarebbe ancora meglio, ma non sono sicuro che sia possibile! – kfmfe04

+0

Quello che intendevo è che ** tu ** hai usato CRTP quando hai ottenuto TBar. È l'unico tipo di figlio di 'TFoo' che vuoi permettere o è ok avere qualcosa come' struct X: TFoo {}; '? – jrok

risposta

1

Presumo che hai fatto un errore nella definizione di TBar e TBas, controllare che la mia modifica è corretta.

#include <type_traits>  

struct Foo { };    // don't allow this 
struct Bar : public Foo { }; // allow this 
struct Baz { };    // don't allow this 

template< typename T > struct TFoo { };      
template< typename T > struct TBar : public TFoo<TBar<T>> { }; 
template< typename T > struct TBaz { };      

template< typename T > 
struct My_Limited_Template 
{ 
     static_assert(
       (std::is_base_of<Foo,T>::value && !std::is_same<T,Foo>::value) 
       || 
       (std::is_base_of<TFoo<T>,T>::value && !std::is_same<T,TFoo<T>>::value), 
       "fail2" 
     ); 
}; 
+1

Non penso che la tua seconda parte sia corretta (perché stai assumendo che la domanda sia sbagliata?). IIUC, la domanda richiede che 'T' sia una sottoclasse di qualche istanza (non specificata) di' TFoo', mentre la tua risposta richiede che 'T' sia una sottoclasse di specificamente' TFoo '. – Mankarse

Problemi correlati