Checking whether a function (not a method) exists in c++11 via templates

耗尽温柔 提交于 2019-12-01 08:03:56

I find the void_t trick to be usually preferable to the traditional SFINAE method shown in the other answer.

template<class...> using void_t = void; // now in the C++17 working paper!
// GCC <= 4.9 workaround:
// template<class...> struct voider { using type = void; };
// template<class... T> using void_t = typename voider<T...>::type;

template<class, class = void>
struct is_ostreamable : std::false_type {};

template<class T>
struct is_ostreamable<T, void_t<decltype(std::declval<std::ostream&>() <<
                                         std::declval<T>())>> : std::true_type {};

The partial specialization is selected if and only if the expression is well-formed.

Demo. Note that the & in std::declval<std::ostream&>() is important, because otherwise std::declval<std::ostream>() is an rvalue and you'll get ostream's catchall rvalue stream insertion operator, and report that everything is streamable.

The above code checks for an operator<< that can accept a T rvalue . If you want to check for one that accepts an lvalue T, then use std::declval<T&>().

Using SFINAE, it's possible like this:

template <typename T>
class has_ostream_lshift
{
  struct no {};

  template <typename T2>
  static decltype(std::declval<std::ostream&>() << std::declval<T2>()) test(int);

  template <typename T2>
  static no test(...);

public:
  enum { value = ! std::is_same<no, decltype(test<T>(0))>::value};
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!