【问题标题】:Member detection based on custom void_t implementation基于自定义 void_t 实现的成员检测
【发布时间】:2018-09-14 07:54:44
【问题描述】:

我有这本书 C++ Templates the complete guide,我正在尝试实现一些描述的技术。其中之一是成员函数检测,但我的实现似乎不起作用。

我不能使用 void_t,因为我使用的是 C++11,但我复制了定义,所以这应该不是问题。

以下是代码:

namespace nt_detail
  {
  template< class... >
  using void_t = void;
  }

template<typename T, typename = nt_detail::void_t<>>
struct HasHelloMember
    : std::false_type {};

template<typename T>
struct HasHelloMember<T,
    nt_detail::void_t<decltype(std::declval<T>().hello())>>
       : std::true_type {};

这里是测试:

class ZZZ
  {

  };

class ZZZ2
  {
  public:
  void hello()
    {}
  };

int main()
  {
  if(HasHelloMember<ZZZ>::value)
    {
    std::cout << "ZZZ has hello" << std::endl;
    }
  else
    {
    std::cout << "ZZZ has NOT hello" << std::endl;
    }



if(HasHelloMember<ZZZ2>::value)
  {
  std::cout << "ZZZ2 has hello" << std::endl;
  }
else
  {
  std::cout << "ZZZ2 has NOT hello" << std::endl;
  }
}

在这两种情况下,我都会得到“你好”。我的 void_t 实现可能有问题吗?

【问题讨论】:

  • 你用的是什么编译器? Could not reproduce.
  • 我使用的是 gcc 4.8.5
  • 有可能升级吗? gcc5.1 是你需要的。
  • @YSC 你是说它只是一个编译器错误还是一个 C++11“问题”?
  • 这是 C++11 的非保证,已在 C++14 中删除,但编译器之前已修复;至少 gcc 和 clang。

标签: c++ templates traits template-meta-programming sfinae


【解决方案1】:

试试这个void_t的定义,除非你使用的是C++17:

template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;

根据https://en.cppreference.com/w/cpp/types/void_t

直到 CWG 1558(C++14 缺陷),别名模板中未使用的参数 不能保证确保 SFINAE 并且可以忽略,所以更早 编译器需要更复杂的void_t定义,比如

这是 5.1 版之前的 gcc 问题。

【讨论】:

  • @YSC 正如文字所写 - 它可能有效,但不能保证
  • 谢谢!它确实是 void_t 定义,现在它可以正常工作了。 PS有连接问题
  • 这是一个很好的答案。仅供参考这个怪癖has been resolved in gcc5.1。 @bartop 您可以在答案中添加它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
  • 2019-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多