C++ SFINAE 未失败

2024-04-21

Code:

#include <iostream>


using std::nullptr_t;

template<typename... T>
using nullptr_vt = nullptr_t;

struct not_addable{};


template<
  typename T, 
  nullptr_vt<decltype(std::declval<T>() + std::declval<T>())> TSfinae = nullptr>
bool test_addable(int)
{ return true; }

template<typename>
bool test_addable(...)
{ return false; }


int main()
{
  std::cout << std::boolalpha;

  std::cout << test_addable<int>(0) << std::endl;
  std::cout << test_addable<not_addable>(0) << std::endl;

  // Gives error ("invalid operands to binary expression"):
  // nullptr_vt<decltype(std::declval<not_addable>() + std::declval<not_addable>())> a{};
}

我以为这会打印:

true
false

,但事实并非如此。它打印:

true 
true

。至少在https://repl.it/@Hrle/sfinaetemplatesuccess https://repl.it/@Hrle/sfinaetemplatesuccess.

我以为nullptr_vt<decltype(std::declval<T>() + std::declval<T>())>从第一次过载开始将是一个错误not_addable并且它会将其从过载集中丢弃,从而选择第二个过载。

编译器是否有能力丢弃类型TSfinae如果有默认值?


我以为nullptr_vt<decltype(std::declval<T>() + std::declval<T>())>对于 not_addable 来说,第一个重载将是一个错误,它将从重载集中丢弃它,从而选择第二个重载。

这个想法实际上很好,问题在于 GCC 和nullptr_vt

这行:

nullptr_vt<decltype(std::declval<T>() + std::declval<T>())> TSfinae = nullptr

在 GCC 10.2 上您不希望它工作的地方可以工作,但在 Clang 11.0.1 上却是正确的。将其更改为

nullptr_vt<decltype(std::declval<T>() + std::declval<T>())> *TSfinae = nullptr

两者都是正确的,更简单的也是正确的

typename TSfinae = nullptr_vt<decltype(std::declval<T>() + std::declval<T>())>
typename _ = decltype(std::declval<T>() + std::declval<T>())

最后是 make_void 技巧

template<typename... T> struct make_nullptr_vt { using type = nullptr_t; };

template<typename T>
using nullptr_vt = typename make_nullptr_vt<T>::type;

还修复了 GCC 上的原始版本。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ SFINAE 未失败 的相关文章

随机推荐