2014-09-12 29 views
5

TLDR: Son paragrafa bakın. enable_if türünde belirli bir şablon sınıfı yok

Ben

bir operator& şöyle birkaç şablon sınıfları için tanımlanan vardır: Bu sadece iyi çalışır

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; 
} 

.

sorun sadece bir tarafında veya bir ve operasyonun diğer yanda izin verilen bir değil operasyonu eklemek istediğinizde oluşur ve ClassAnd yerine ClassAndNot bir örneğini döndürmesi gerekir:

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; 

Bu bir ClassAnd döndürmek için bir operator& rastgele bir sağ taraf vebirdöndürmek için sağ tarafa doğru sağ tarafı arasında bir belirsizlik ile sonuçlanır.


Soru: sağ taraftaki türlerinden ClassNot herhangi birinin olup olmadığını

Nasıl std::enable_if ilk operator& devre dışı bırakmak için buraya kullanılabilir? Bir tarafın diğerinin şablon örneği ise, std::is_same gibi bir şey var mı?

p.s. ideone üzerinde tam bir çalışma örneği bulabilirsiniz.

cevap

6

Bunun için kendi özelliğini inşa gerekir: Bir çok amaçlı özellik

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

Tabii

, sen genellemeler ile Çıldırabiliriz ve oluşturun:

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

İkinci örneğiniz tam olarak aradığım şeydi (ancak standart kitaplık tarafından sağlandı). İşleri biraz daha basit tutmak için ilk örnekle gideceğim. Teşekkürler! – zennehoy

+0

@zennehoy Standart kitaplık tarafından sağlanmayan nedenlerden birinin, genellikle şablon olmayan veya şablon şablonu parametrelerini alan sınıf şablonları için tam olarak yazmanın bir yolu bulunmadığını tahmin ediyorum. – Angew

İlgili konular