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(使用前将#替换为@)