【发布时间】:2017-03-25 14:45:19
【问题描述】:
#include <iostream>
#include <type_traits>
template<typename T>
struct A
{
using m = std::remove_pointer_t<T>&;
};
template
<
typename T,
typename = std::void_t<>
>
struct Test
{
enum { value = 0 };
};
template<typename T>
struct Test<T, typename A<T>::m>
{
enum { value = 1 };
};
int main()
{
std::cout << Test<void*&>::value; // ok, output 0
std::cout << Test<void*>::value; // error : cannot form a reference to 'void'
}
第一种情况输出0,表示选择了主模板。所以,我认为第二种情况也应该选择主模板而不是专用模板;那么,应该不会有错误。
预计Test<void*&>可以;让我吃惊的是Test<void*>应该不行!
为什么 SFINAE 在后一种情况下不起作用?
【问题讨论】:
-
可能是这种情况,因为
A<T>::m是不可演绎的上下文。 -
如果是,为什么前一种情况可以?
-
因为参考崩溃和
remove_pointer无效。 -
没有选择专用模板并不意味着它没有被实例化。您的第二种情况(如果有效)也将选择主模板。只需将
void替换为int即可看到它会打印出00。 -
g++ 6.3.0(-std=c++17) andclang 3.8.0(-std=c++1z) andVisual Studio 2015all print0forTest<int*>::value.
标签: c++ overloading sfinae c++17 typetraits