Hrv*_*rić 6 c++ templates sfinae
代码:
#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{};
}
Run Code Online (Sandbox Code Playgroud)
我以为这会打印:
true
false
Run Code Online (Sandbox Code Playgroud)
,但事实并非如此。它打印:
true
true
Run Code Online (Sandbox Code Playgroud)
. 至少在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
Run Code Online (Sandbox Code Playgroud)
在 GCC 10.2 上您不希望它工作的地方可以工作,但在 Clang 11.0.1 上却是正确的。将其更改为
nullptr_vt<decltype(std::declval<T>() + std::declval<T>())> *TSfinae = nullptr
Run Code Online (Sandbox Code Playgroud)
两者都是正确的,更简单的也是正确的
typename TSfinae = nullptr_vt<decltype(std::declval<T>() + std::declval<T>())>
typename _ = decltype(std::declval<T>() + std::declval<T>())
Run Code Online (Sandbox Code Playgroud)
最后是 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;
Run Code Online (Sandbox Code Playgroud)
还修复了 GCC 上的原始版本。
| 归档时间: |
|
| 查看次数: |
104 次 |
| 最近记录: |