C++ SFINAE 没有失败 [英] C++ SFINAE not failing

查看:32
本文介绍了C++ 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{};
}

我认为这会打印:

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?

推荐答案

我认为第一次重载的 nullptr_vt() + std::declval())> 对于 not_addable 和它将从重载集中丢弃它,从而选择第二个重载.

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.

这个想法其实很好,问题只在于 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 没有失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆