2012-12-19 22 views
6

Nie mogę znaleźć dobrego rozwiązania dla używania SFINAE z klasami szablonów variadic.SFINAE z klasami szablonów variadic?

Powiedzmy mam zmiennej liczbie argumentów szablonu przedmiot, który nie lubi nazwy:

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

I klasy, która wygodnie sprawdza jeśli paczka argument zawiera nazwy:

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

Jak używać to specjalizować NoRef dla przypadku, gdy referencje są obecne w pakiecie arg?

Odpowiedz

9

nie używać SFINAE, ale w zasadzie robi to, co masz zamiar:

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. Ale myślę, że 'szablon struct NoRef: NoRef_ :: value, Args ...> {};' byłoby lepiej. Teraz 'NoRef' jest szablonem innej klasy bez parametru szablonu nie typu (tj. Wartości boolowskiej). – Nawaz

+0

Podoba mi się to rozwiązanie, mimo że nie mogę pseudonimować szablonów w MSVC. Ale Nawaz również to rozwiązał. –

6

Obawiam się, że nie jest to możliwe, ponieważ pakiety szablonów są niewygodne. Możesz jednak spakować paczki.

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

Dostosowujemy czek odniesienie:

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

A teraz możemy użyć Pack:

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

template <typename... Args> 
class NoRef<Pack<Args...>, false> { 
    // no reference in Args... here 
}; 
Powiązane problemy