2017-02-07 90 views
7

Mam problem z tworzeniem funkcji, która dla danego typu, jeśli pochodzi od innego, robi coś, a dla wszystkich innych przypadków robi coś innego. Mój kod:Funkcja szablonu C++ dla klasy pochodnej ze std :: is_base_of

class BaseClass {}; 
class DerivedClass : public BaseClass {}; 

template <typename T> 
void Function(typename std::enable_if<std::is_base_of<BaseClass, T>::value, T>::type && arg) { 
    std::cout << "Proper"; 
} 

template <typename T> 
void Function(T && arg) { 
    std::cout << "Improper"; 
} 

void test() { 
    Function(DerivedClass{}); 
} 

Dla klasy DeriviedClass i inne oparte na BaseClass Chciałbym funkcję coutingProper zadzwonić, ale CoutsImproper. Jakieś sugestie?

+2

T jest w niewyspecjalizowanych wywnioskować kontekście tutaj, aby przejść enable_if typu Wynik: 'auto funkcji (T) -> typename enable_if :: typem. –

Odpowiedz

6

Jak wspomniano w komentarzach do pytania, wyrażenia SFINAE nie będą działać tak, jak to zrobiliście.
To powinno być zamiast coś takiego:

template <typename T> 
typename std::enable_if<std::is_base_of<BaseClass, T>::value>::type 
Function(T && arg) { 
    std::cout << "Proper" << std::endl; 
} 

template <typename T> 
typename std::enable_if<not std::is_base_of<BaseClass, T>::value>::type 
Function(T && arg) { 
    std::cout << "Improper" << std::endl; 
} 

wyrażenia SFINAE będzie włączyć lub wyłączyć Function w zależności od faktu, że BaseClass jest podstawa T. Typ powrotu to void w obu przypadkach, ponieważ jest to domyślny typ dla std::enable_it, jeśli go nie zdefiniujesz.
Zobacz na coliru.

Istnieją inne ważne alternatywy, a niektóre z nich zostały wymienione w innych odpowiedziach.

+1

Czy istnieje teraz możliwość przeciążenia tej funkcji dla określonego typu, np. pływak? – miqelm

+1

@miqelm przeciążone funkcje nie-szablonowe są preferowane w stosunku do szablonowych, więc tak (patrz [tutaj] (http://coliru.stacked-crooked.com/a/b49a7e7f56954978) jako przykład). – skypjack

3
template <typename T> 
auto Function(T && arg) -> typename std::enable_if<std::is_base_of<BaseClass, T>::value>::type 
{ 
    std::cout << "Proper"; 
} 

template <typename T> 
auto Function(T && arg) -> typename std::enable_if<!std::is_base_of<BaseClass, T>::value>::type 
{ 
    std::cout << "Improper"; 
} 

wandbox example

3
#include <typeinfo> 
#include <iostream> 

class BaseClass {}; 
class DerivedClass : public BaseClass {}; 
class OtherClass {}; 

template <typename T,typename = typename std::enable_if<std::is_base_of<BaseClass, T>::value, T>::type> 
void Function(T && arg) 
{ 
    std::cout << "Proper" << std::endl; 
} 

void Function(...) 
{ 
    std::cout << "Improper"<< std::endl; 
} 

int main() 
{ 
    Function(DerivedClass{}); 
    Function(BaseClass{}); 
    Function(OtherClass{}); 
} 
+0

'Funkcja (OtherClass {});' może być używana do łatwego rozbicia. Zbyt słaby roztwór. – skypjack