为什么这个SFINAE代码段不能在g ++中工作,而可以在MSVC中工作? [英] Why this SFINAE snippet is not working in g++, but working in MSVC?
问题描述
在MSVC2017中,此方法工作正常,两个static_asserts均未按预期触发:
In MSVC2017 this works fine, both static_asserts are NOT triggered as expected:
template <typename T>
struct do_have_size {
template <typename = decltype(std::declval<T>().size())>
static std::true_type check(T);
static std::false_type check(...);
using type = decltype(check(std::declval<T>()));
};
int main() {
using TR = typename do_have_size<std::vector<int>>::type;
using FL = typename do_have_size<int>::type;
static_assert(std::is_same<TR, std::true_type>::value, "TRUE");
static_assert(std::is_same<FL, std::false_type>::value, "FALSE");
}
但是,如果我使用g ++ 7.1或clang 4.0进行编译,则会得到以下结果编译器错误:
However, if I compile in g++7.1 or clang 4.0 I get following compiler error:
In instantiation of 'struct do_have_size<int>':
20:39: required from here
9:24: error: request for member 'size' in 'declval<do_have_size<int>::TP>()', which is of non-class type 'int'
据我对SFINAE的理解,对于<$ c,替换 true_type
返回函数应该失败$ c> int 参数和下一个函数将被选择,就像在MSVC中一样。为什么clang和g ++根本不编译它?
From my understanding of SFINAE, substition of true_type
returning function should fail for int
parameter and next function shall be chosen, like it is done in MSVC. Why clang and g++ are not compiling it at all?
我仅使用 -std = c ++ 17
开关进行编译,也许还需要更多的东西吗?
I've compiled with -std=c++17
switch only, maybe something more is needed?
推荐答案
这与默认模板参数是否为功能模板签名的一部分完全无关。
This has absolutely nothing to do with whether default template arguments are part of a function template's signature.
真正的问题是 T
是一个类模板参数,当您实例化该类模板的定义时,实现可以立即将其替换为您的默认模板自变量 decltype(std :: declval< T>()。size())
在模板自变量推导之外,如果 size
不存在。
The real problem is that T
is a class template parameter, and when you instantiate the class template's definition, the implementation can immediately substitute it into your default template argument, decltype(std::declval<T>().size())
outside of template argument deduction, which causes a hard error if size
is not present.
解决方法很简单;只需使其依赖于函数模板的参数即可。
The fix is simple; simply make it depend on a parameter of the function template.
template <typename U, typename = decltype(std::declval<U>().size())>
static std::true_type check(U);
(您的实现还存在其他问题,例如需要可移动构造的非抽象 T
并不需要 size()
即可被常量调用,但它们不是导致错误的原因您正在看到。)
(There are other problems with your implementation, such as it requires a move-constructible non-abstract T
and doesn't require size()
to be const-callable, but they aren't the cause of the error you are seeing.)
这篇关于为什么这个SFINAE代码段不能在g ++中工作,而可以在MSVC中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!