2017-01-10 40 views
2

至少我认为,下面的代码片段尽可能直接适用于专业化的SFINAE模板:SFINAE专业化没有得到应用

最后一行是主要点,发生故障的位置。专门的foo模板的定义决定了bar模板的专业化程度,或者我想要的。其他bar专业化可以在其他地方定义,或者也许使用任意类型可以简单地保持不受支持。据我所知,相同的模式被广泛建议与enable_if一起使用。

template <typename T> 
struct foo; 

template <> 
struct foo<int> { 
    using type = int; 
}; 

template <typename T, typename use = void> 
struct bar; 

template <typename T> 
struct bar<T, typename foo<T>::type> { 
    using type = typename foo<T>::type; 
}; 

using good = typename foo<int>::type; 
using bad = typename bar<int>::type; 

在g ++中,使用14或17标准,结果如下所示。看起来bar特化没有得到应用,编译器正在使用非特定(空)的定义。为什么?

$ g++ --std=c++14 special.cpp -o special 
special.cpp:18:32: error: ‘type’ in ‘struct bar<int>’ does not name a type 
using bad = typename bar<int>::type; 
+1

'栏 ::类型><==>酒吧''栏!=条' – 0x499602D2

+0

您实例'栏'。你为什么期望编译器使用除“空”定义之外的其他内容? “bar”的“非空”专业化甚至不能与''参数进行远程匹配。 – AnT

回答

4
template <typename T> 
struct bar<T, typename foo<T>::type> { 
    using type = typename foo<T>::type; 
}; 

应该

template <typename T> 
struct bar<T, std::void_t<typename foo<T>::type>> { 
    using type = typename foo<T>::type; 
}; 

use应始终void

这就是为什么命名为AlwaysVoid会更好。 (或使用的东西像Enabler它的作用)

template <typename T, typename AlwaysVoid = void> 
struct bar;