为什么这个SFINAE没有按预期工作?

时间:2017-05-21 07:09:37

标签: c++ sfinae c++17 typetraits

好的,为什么is_destructible的C ++ 17实现不适用于引用类型?我希望T&T&&的部分特化会吸收任何引用类型,但相反,似乎int&被第四行和producing a hard error.抓住了

namespace detail {
 template<class T, class Enable> struct is_destructible_impl : false_type {};
 template<class T> struct is_destructible_impl<T&, void>  : true_type {};
 template<class T> struct is_destructible_impl<T&&, void> : true_type {};
 template<class T> struct is_destructible_impl<T, decltype(declval<T&>().~T())> : true_type {};
}

template<class T> struct is_destructible :
    detail::is_destructible_impl<remove_all_extents_t<T>, void> {};

int main()
{
    static_assert(is_destructible<int&>::value, "oops");
}

是什么让编译器更喜欢将<int&, void><T, (complicated expression that fails)>匹配,而不是与诱人的<T&, void>相匹配?

更新:事实证明这是一个GCC错误。 Clang接受代码就好了。所以,后续问题:是否有一种解决方法可以使像is_destructible这样的东西在没有太多额外编码的情况下在GCC上运行?

1 个答案:

答案 0 :(得分:4)

看起来GCC - 错误地 - 在不匹配的伪测试器调用上发出硬错误。

template<class T, class U>
auto f(int) -> decltype(std::declval<T&>().~U());

template<class T, class U>
int f(double);

using t = decltype(f<int, double>(0));

struct C {}; struct D {};
using tt = decltype(f<C, D>(0));

GCC在t但与tt发出类似错误。

Clang编译你的代码就好了。

  

是否有一种解决方法可以做到这样的事情   is_destructible在没有太多额外编码的情况下就GCC工作了吗?

只需移出参考专精:

namespace detail {
 template<class T, class Enable> struct is_destructible_impl : false_type {};
 template<class T> struct is_destructible_impl<T, decltype(declval<T&>().~T())> : true_type {};
}

template<class T> struct is_destructible :
    detail::is_destructible_impl<remove_all_extents_t<T>, void> {};
template<class T> struct is_destructible<T&>  : true_type {};
template<class T> struct is_destructible<T&&> : true_type {};