2012-06-15 21 views
26

Sto costruendo un controllo di input che deve avere funzioni specifiche per interi e/o double (ad esempio 'isPrime' dovrebbe essere disponibile solo per numeri interi).std :: enable_if: parametro parametro vs modello

Se sto usando enable_if come parametro è perfettamente funzionante:

template <class T> 
class check 
{ 
public: 
    template< class U = T> 
    inline static U readVal(typename std::enable_if<std::is_same<U, int>::value >::type* = 0) 
    { 
     return BuffCheck.getInt(); 
    } 

    template< class U = T> 
    inline static U readVal(typename std::enable_if<std::is_same<U, double>::value >::type* = 0) 
    { 
     return BuffCheck.getDouble(); 
    } 
}; 

ma se sto usando come paramater modello (come dimostrato su http://en.cppreference.com/w/cpp/types/enable_if)

template <class T> 
class check 
{ 
public: 
    template< class U = T, class = typename std::enable_if<std::is_same<U, int>::value>::type > 
    inline static U readVal() 
    { 
     return BuffCheck.getInt(); 
    } 

    template< class U = T, class = typename std::enable_if<std::is_same<U, double>::value>::type > 
    inline static U readVal() 
    { 
     return BuffCheck.getDouble(); 
    } 
}; 

poi ho ha il seguente errore:

error: ‘template<class T> template<class U, class> static U check::readVal()’ cannot be overloaded 
error: with ‘template<class T> template<class U, class> static U check::readVal()’ 

Non riesco a capire o cosa c'è di sbagliato nella seconda versione.

+0

Forse irrilevante, ma in VS2010 non posso farlo perché gli argomenti di template di default sono ammessi solo per i modelli di classe - non so circa g ++ – David

+2

Questo è pedante, ma il 'inline' parola chiave su un metodo membro o un modello non è necessario e certamente non un membro che è anche un modello ;-) – AJG85

risposta

31

Gli argomenti del modello predefinito non fanno parte della firma di un modello (quindi entrambe le definizioni tentano di definire lo stesso modello due volte). I loro tipi di parametri fanno comunque parte della firma. Così si può fare

template <class T> 
class check 
{ 
public: 
    template< class U = T, 
      typename std::enable_if<std::is_same<U, int>::value, int>::type = 0> 
    inline static U readVal() 
    { 
     return BuffCheck.getInt(); 
    } 

    template< class U = T, 
      typename std::enable_if<std::is_same<U, double>::value, int>::type = 0> 
    inline static U readVal() 
    { 
     return BuffCheck.getDouble(); 
    } 
}; 
+1

+1, penso che questo sembra molto più pulito rispetto all'altro approccio. – ildjarn

+0

Soluzione abbastanza intelligente! – plasmacel

+1

Quindi un parametro di modello di tipo predefinito (che ha un tipo predefinito) non fa parte della firma di un modello, ma un parametro di modello non di tipo predefinito (che ha un valore integrale costante predefinito). È corretto? – Alan

7

Il problema è che il compilatore vede 2 overload dello stesso metodo, entrambi che contengono gli stessi argomenti (nessuno, in questo caso) e lo stesso valore di ritorno. Non è possibile fornire tale definizione. Il modo più pulito per farlo è usare SFINAE sul valore di ritorno della funzione:

template <class T> 
class check 
{ 
public: 
    template< class U = T> 
    static typename std::enable_if<std::is_same<U, int>::value, U>::type readVal() 
    { 
     return BuffCheck.getInt(); 
    } 

    template< class U = T> 
    static typename std::enable_if<std::is_same<U, double>::value, U>::type readVal() 
    { 
     return BuffCheck.getDouble(); 
    } 
}; 

In questo modo, si sta fornendo 2 sovraccarichi differenti. Uno restituisce un int, l'altro restituisce un doppio e solo uno può essere istanziato utilizzando un certo T.

Problemi correlati