2012-12-19 12 views
6

Ich kann nicht scheinen, eine gute Lösung für die Verwendung von SFINAE mit variadic Vorlagenklassen zu finden.SFINAE mit variadischen Template-Klassen?

Sagen wir, ich ein variadische Template-Objekt haben, die keine Referenzen mag:

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

Und eine Klasse, die, wenn ein Argument Pack enthält Verweise bequem überprüft:

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

Wie verwende ich dies zu spezialisieren NoRef für den Fall, dass Referenzen in der Arg-Packung vorhanden sind?

Antwort

9

Diese verwendet nicht SFINAE, aber im Wesentlichen tut, was Sie beabsichtigen:

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. Aber ich denke 'Vorlage Struktur NoRef: NoRef_ :: Wert, Args ...> {};' wäre besser. Nun ist 'NoRef' eine andere Klassenvorlage ohne Nicht-Typ-Vorlagenparameter (d. H. Boolescher Wert). – Nawaz

+0

Ich mag diese Lösung, obwohl ich Vorlagen in MSVC noch nicht Aliasvorlagen kann. Aber Nawaz hat auch dafür eine Lösung gefunden. –

6

Ich fürchte, das ist nicht möglich wie es ist, weil Vorlagenpakete unhandlich sind. Sie können jedoch Pakete packen.

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

Wir passen die Referenzprüfung:

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

Und jetzt können wir nutzen die Pack:

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

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