为什么这个SFINAE代码段不能在g ++中工作,而可以在MSVC中工作? [英] Why this SFINAE snippet is not working in g++, but working in MSVC?

查看:62
本文介绍了为什么这个SFINAE代码段不能在g ++中工作,而可以在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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆