问题描述
代码:
#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
,但事实并非如此.它打印:
, but it doesn't. It prints:
true
true
.至少在 https://repl.it/@Hrle/sfinaetemplatesuccess 上.
我认为第一次重载的 nullptr_vt() + std::declval())>
对于 not_addable
并将其从重载集中丢弃,从而选择第二个重载.
如果存在默认值,编译器是否有能力丢弃 TSfinae
的类型?
. At least on https://repl.it/@Hrle/sfinaetemplatesuccess.
I thought that nullptr_vt<decltype(std::declval<T>() + std::declval<T>())>
from the first overload would be an error for not_addable
and it would discard it from the overload set, thus choosing the second overload.
Does the compiler have the ability to discard the type of TSfinae
if there is a default?
推荐答案
这个想法其实很好,问题只在于 GCC 和 nullptr_vt
The idea is actually fine, the problem is just with GCC and nullptr_vt
这一行:
nullptr_vt<decltype(std::declval<T>() + std::declval<T>())> TSfinae = nullptr
在您不希望它在 GCC 10.2 上工作但在 Clang 11.0.1 上是正确的.改成
works where you don't want it to on GCC 10.2 but is correct on Clang 11.0.1. Changing it to
nullptr_vt<decltype(std::declval<T>() + std::declval<T>())> *TSfinae = nullptr
两者都是正确的,更简单的也是如此
is correct on both, as are the simpler
typename TSfinae = nullptr_vt<decltype(std::declval<T>() + std::declval<T>())>
typename _ = decltype(std::declval<T>() + std::declval<T>())
最后是 make_void 技巧
And finally the make_void trick
template<typename... T> struct make_nullptr_vt { using type = nullptr_t; };
template<typename T>
using nullptr_vt = typename make_nullptr_vt<T>::type;
也修复了 GCC 上的原始版本.
fixes the original version on GCC as well.
这篇关于C++ SFINAE 没有失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!