2014-09-12 12 views
5

TLDR: Zobacz ostatni akapit.typ włączania i wyłączania nie należy do określonej klasy szablonów

Mam operator& zdefiniowane dla kilku klas szablonu tak:

template <typename T> 
struct Class { 
    Class(T const &t) { } 
}; 

template <typename T_Lhs, typename T_Rhs> 
struct ClassAnd { 
    ClassAnd(T_Lhs const &lhs, T_Rhs const &rhs) { } 
}; 

template <typename T, typename T_Rhs> 
ClassAnd<Class<T>, T_Rhs> operator&(Class<T> const &lhs, T_Rhs const &rhs) { 
    return ClassAnd<Class<T>, T_Rhs>(lhs, rhs); 
} 

template <typename T0, typename T1, typename T_Rhs> 
ClassAnd<ClassAnd<T0, T1>, T_Rhs> operator&(ClassAnd<T0, T1> const &lhs, T_Rhs const &rhs) { 
    return ClassAnd<ClassAnd<T0, T1>, T_Rhs>(lhs, rhs); 
} 

int main() { 
    Class<int> a(42); 
    Class<double> b(3.14); 
    auto c = a & b; 
} 

Działa to dobrze.

Problem pojawia się gdy chcę dodać nie działanie, które jest dozwolone tylko po jednej lub drugiej stronie O mocy i pracy, i musi zwracać instancję ClassAndNot zamiast ClassAnd:

template <typename T> 
struct ClassNot { 
    ClassNot(T const &t) : value(t) { } 
    T value; 
}; 

template <typename T_Lhs, typename T_Rhs> 
struct ClassAndNot { 
    ClassAndNot(T_Lhs const &lhs, T_Rhs const &rhs) { } 
}; 

template <typename T_Lhs, typename T_Rhs> 
ClassAndNot<T_Lhs, T_Rhs> operator&(T_Lhs const &lhs, ClassNot<T_Rhs> const &rhs) { 
    return ClassAndNot<T_Lhs, T_Rhs>(lhs, rhs.value); 
} 

template <typename T_Rhs> 
ClassNot<T> operator!(T_Rhs const &rhs) { 
    return ClassNot<T_Rhs>(rhs); 
} 

... 

auto c = a & !b; 

ten prowadzi do niejednoznaczności pomiędzy podjęciem arbitralnej prawej strony, aby zwrócić ClassAnd, a po prawej stronie, aby zwrócić prawej stronie, aby zwrócić ClassAndNot.


Pytanie:

Jak można std::enable_if być stosowane tutaj, aby wyłączyć pierwszy operator& jeśli jego prawej stronie jest którykolwiek z rodzajów ClassNot? Czy jest coś w rodzaju std::is_same, które zwraca wartość true, jeśli jedna strona jest wzorcową instancją drugiej?

p.s. Pełny przykład pracy można znaleźć na stronie ideone.

Odpowiedz

6

powinien być w stanie skonstruować własną cechę tego:

template <class T> 
struct IsClassNot : std::false_type 
{}; 

template <class T> 
struct IsClassNot<ClassNot<T>> : std::true_type 
{}; 


template <typename T, typename T_Rhs> 
typename std::enable_if<!IsClassNot<T_Rhs>::value, 
ClassAnd<Class<T>, T_Rhs>>::type operator&(Class<T> const &lhs, T_Rhs const &rhs) { 
    return ClassAnd<Class<T>, T_Rhs>(lhs, rhs); 
} 

Live example


Oczywiście, można zwariować z uogólnień i stworzyć cechę wszystkim uniwersalny:

template <class T, template <class...> class TT> 
struct is_instantiation_of : std::false_type 
{}; 

template <template <class... > class TT, class... A> 
struct is_instantiation_of<TT<A...>, TT> : std::true_type 
{}; 

template <class T> 
using IsClassNot = is_instantiation_of<T, ClassNot>; 

Live example

+0

Twój drugi przykład jest dokładnie tym, czego szukałem (ale dostarczonym przez standardową bibliotekę). Pójdę z pierwszym przykładem, aby trochę uprościć sprawę. Dzięki! – zennehoy

+0

@zennehoy Domyślam się, że jednym z powodów, dla których nie jest dostarczana przez standardową bibliotekę, jest to, że nie ma sposobu, aby napisać ją w pełni ogólnie dla szablonów klas, które przyjmują dowolne parametry szablonu bez szablonu lub szablonu. – Angew

Powiązane problemy