2015-12-19 8 views
6

Also, bin ich das durch den Code irgendwo auf dieser Web-Seite setzt Beispiel folgende: http://eli.thegreenplace.net/2014/sfinae-and-enable_if/SFINAE: std :: enable_if als Funktionsargument

Hier ist, was ich habe:

template<typename T> 
void fun(const typename std::enable_if_t<std::is_integral<T>::value, T>& val) { 
    std::cout << "fun<int>"; 
} 

template<typename T> 
void fun(const typename std::enable_if_t<std::is_floating_point<T>::value, T>& val) { 
    std::cout << "fun<float>"; 
} 

int main() 
{ 
    fun(4); 
    fun(4.4); 
} 

Auf diese Weise Ich müsste schreiben:

fun<int>(4); 
fun<double>(4.4); 

Wie würde ich das vermeiden?

Compiler beschwert sich, dass es den Parameter T nicht ableiten kann.

Antwort

5

Die Beispiele sind falsch, da T in einem non-deduced context ist. Wenn Sie nicht die Funktion wie fun<int>(4); aufrufen, wird der Code nicht kompiliert, aber das ist wahrscheinlich nicht das, was der Autor zeigen wollte.

Die korrekte Verwendung wäre es, T vom Compiler abzuleiten und eine SFINAE-Bedingung woanders zu platzieren, z. in einem Rückgabetyp Syntax:

template <typename T> 
auto fun(const T& val) 
    -> typename std::enable_if<std::is_integral<T>::value>::type 
{ 
    std::cout << "fun<int>"; 
} 

template <typename T> 
auto fun(const T& val) 
    -> typename std::enable_if<std::is_floating_point<T>::value>::type 
{ 
    std::cout << "fun<float>"; 
} 

DEMO

Auch die typename s in Ihrem Code widersprechen Ihre Benutzung std::enable_if_t.

Verwenden entweder (C++ 11):

typename std::enable_if<...>::type 

oder (C 14 ++):

std::enable_if_t<...> 

Wie würde, dass die Arbeit in einem Konstruktor die doesn haben Sie keinen Rückgabetyp?

Bei Bauer kann der SFINAE Zustand in einer Liste Template-Parameter ausgeblendet werden:

struct A 
{  
    template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> 
    A(const T& val) 
    { 
     std::cout << "A<int>"; 
    } 

    template <typename T, typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0> 
    A(const T& val) 
    { 
     std::cout << "A<float>"; 
    } 
}; 

DEMO 2

+0

Ich sehe. Wie würde das in einem Konstruktor funktionieren, der keinen Rückgabetyp hat? – DeiDei

+0

@DeiDei siehe das Update –

+0

Was ist die Bedeutung der Verwendung von 'int' als zweites Argument von' std :: enable_if'? Ist es willkürlich? Oder liegt es daran, dass "int = 0" sicher ist? – Jacob

1

Abzug zu ermöglichen, benötigen Sie einen Funktionsparameter, die auf T unkompliziert basierten . Sie müssen dann herausfinden, wo Sie Ihre enable_if setzen (die in der Tat nicht T abgeleitet werden kann). Übliche Optionen sind der Rückgabetyp oder ein zusätzlicher Standardparameter, den Sie ignorieren.

Einige gute Beispiele hier: http://en.cppreference.com/w/cpp/types/enable_if