2012-12-19 24 views
6

Değişken şablon sınıflarıyla SFINAE'yi kullanmak için iyi bir çözüm bulamıyorum.SFINAE?

template<typename... Args> 
class NoRef 
{ 
    //if any of Args... is a reference, this class will break 
    //for example: 
    std::tuple<std::unique_ptr<Args>...> uptrs; 
}; 

Ve elverişli bir argüman paketi başvuruları içeriyorsa kontrol eden bir sınıf: ben kullanırım nasıl

template<typename T, typename... Other> 
struct RefCheck 
{ 
    static const bool value = std::is_reference<T>::value || RefCheck<Other...>::value; 
}; 
template<typename T> 
struct RefCheck<T> 
{ 
    static const bool value = std::is_reference<T>::value; 
}; 

ı başvuruları sevmez variadic şablon nesnesi var diyelim Bu arg paketi içinde mevcut referanslar için NoRef uzmanlaşmak için?

cevap

9

Bu SFINAE kullanabilirsiniz, ancak aslında sen niyetinde ne yaptığını değildir:

template<bool Ref, typename... Args> 
class NoRef_; 

template<typename... Args> 
class NoRef_<false, Args...> 
{ 
    std::tuple<std::unique_ptr<Args>...> uptrs; 
}; 
template<typename... Args> 
class NoRef_<true, Args...> 
{ 
    // contains reference 
}; 

template<typename... Args> 
using NoRef = NoRef_<RefCheck<Args...>::value, Args...>; 

// alternative from Nawaz 

template<typename... Args> struct NoRef : NoRef_<RefCheck<Args...>::value, Args...> {} 
+0

+1. Ama bence struct NoRef: NoRef_ :: value, Args ...> {}; 'daha iyi olurdu. Şimdi 'NoRef', non-type şablon parametresi olmayan (yani boolean değeri) farklı bir sınıf şablonudur. – Nawaz

+0

Bu çözümü, MSVC'de henüz takma ad yapılamamış olmama rağmen sevdim. Fakat Nawaz buna da bir çözüm getirdi. –

6

Bu, çünkü mümkün değil çünkü, çünkü şablon paketleri hantaldır. Ancak paketleri toplayabilirsiniz.

// Used to transport a full pack in a single template argument 
template <typename... Args> struct Pack {}; 

Biz referans kontrol uyarlamak:

template <typename T, typename... Other> 
struct RefCheck 
{ 
    static const bool value = std::is_reference<T>::value 
          || RefCheck<Other...>::value; 
}; 

template <typename T> 
struct RefCheck<T> 
{ 
    static const bool value = std::is_reference<T>::value; 
}; 

template <typename... Args> 
struct RefCheck<Pack<Args...>>: RefCheck<Args...> {}; 

Ve şimdi kullanabilirsiniz Pack:

template <typename P, bool = RefCheck<P>::value> class NoRef; 

template <typename... Args> 
class NoRef<Pack<Args...>, false> { 
    // no reference in Args... here 
}; 
İlgili konular