2017-03-17 93 views
3

我有下面的類模板:模板偏特SFINAE

template<bool head, bool... tail> 
struct var_and { 
    static constexpr bool value = head && var_and<tail...>::value; 
}; 

template<bool b> struct var_and<b> { 
    static constexpr bool value = b; 
}; 

template<typename... Ts> 
struct type_list {}; 

template <typename T, typename Enable = void> 
class foo; 

template <typename... T> 
class foo<type_list<T...>, std::enable_if_t<var_and<std::is_integral_v<T>...>::value>> {}; 

當我嘗試匹配專業化:

foo<type_list<int, int, int>> test{}; 

我得到一個錯誤:

Error C2079 'test' uses undefined class 'ECS::foo<ECS::type_list<int,int,int>,void>' 

在同時我得到這些錯誤:

more than one partial specialization matches the template argument list of class "ECS::foo<ECS::type_list<int, int, int>, void>" 
"ECS::foo<ECS::type_list<T...>, std::enable_if_t<ECS::var_and<std::is_integral_v<T>...>::value, void>>"   
"ECS::foo<ECS::type_list<T...>, std::enable_if_t<ECS::var_and<std::is_integral_v<T>...>::value, void>>" 
... (The exact same error message 6 more times) 

我該如何使用SFINAE來強制變量類型包中類型的類型特徵?

我沒有麻煩它爲單一類型的參數工作: http://www.cppsamples.com/common-tasks/class-template-sfinae.html

我知道我可以簡單地使用static_assert,但我不知道是否也可能沒有。

+1

從編譯器的輸出似乎使用的是MSVC。這段代碼在gcc和clang中工作得很好(見http://coliru.stacked-crooked.com/a/36b9eecd91763aaf)......那麼,msvc bug?無論是或者你沒有給我們所有正在編譯的代碼:) – Rerito

+0

這個與msvc編譯的確切代碼給出了相同的錯誤:http://rextester.com/NIU85113。所以我假設它是一個錯誤呢? –

+0

其實我現在注意到那個鏈接顯示了一個稍微不同的錯誤。 http://webcompiler.cloudapp.net/上運行的代碼給出了相同的錯誤,它使用了更新的編譯器 –

回答

1

解決方法可能如下所示:

#include <type_traits> 

template <bool...> 
struct bool_pack { }; 

template <bool... Bs> 
using var_and = std::is_same<bool_pack<true, Bs...>, bool_pack<Bs..., true>>; 

template<typename... Ts> 
struct type_list {}; 

template <typename T, typename Enable = void> 
class foo; 

template <typename... T> 
class foo<type_list<T...>, std::enable_if_t<var_and<std::is_integral<T>::value...>::value>> {}; 

int main() 
{ 
    foo<type_list<int, int, int>> {}; 
} 

[live demo]

+0

用你的代替我的var_and確實可以編譯。有趣的..這是一個MSVC的已知問題? –

+0

不知道...這似乎也有問題'std :: is_integral_v '用法我用'std :: is_integral :: value'替換它 –