2012-12-19 105 views
6

我似乎無法找到使用SFINAE和variadic模板類的好解決方案。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; 
}; 

和方便檢查如果有一個參數包包含引用的類:

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

如何使用這是爲了在引用出現在arg包中的情況下專門化NoRef?

回答

9

這不使用SFINAE,但本質上是做你想要什麼:

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。但我認爲'template struct NoRef:NoRef_ :: value,Args ...> {};'會更好。現在'NoRef'是沒有非類型模板參數(即布爾值)的不同類模板。 – Nawaz

+0

我喜歡這個解決方案,儘管我無法在MSVC中使用別名模板。但是,納瓦茲也提供了一個解決方案。 –

6

恐怕這是不可能的,因爲模板包很笨拙。但是,您可以打包。

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

我們適應參考檢查:

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

現在我們可以使用Pack

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

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