通过模板检查c ++ 11中是否存在函数(非方法)

kam*_*iro 3 c++ templates sfinae template-meta-programming c++11

因此,使用SFINAE和c ++ 11,可以根据是否可以替换其中一个模板参数来实现两个不同的模板函数.

例如

struct Boo{
   void saySomething(){ cout << "Boo!" << endl; }
};

template<class X>
void makeitdosomething(decltype(&X::saySomething), X x){
   x.saySomething();
}

template<class X>
void makeitsaysomething(int whatever, X x){
    cout << "It can't say anything!" << endl;
}


int main(){
   makeitsaysomething(3);
   makeitsaysomething(Boo());
}
Run Code Online (Sandbox Code Playgroud)

或者那条线上的东西.

我的问题是..如何做同样的事情,但对于非成员函数?

特别是我试图检查是否有这样的事情:

operator<<(std::ostream& os, X& whateverclass);
Run Code Online (Sandbox Code Playgroud)

那是存在的.有可能测试吗?

编辑:问题不同于:是否可以编写模板来检查函数的存在?因为我试图看一个函数是否存在,而不是一个方法

T.C*_*.C. 7

我发现这个void_t技巧通常比其他答案中显示的传统SFINAE方法更好.

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 {};
Run Code Online (Sandbox Code Playgroud)

当且仅当表达式格式正确时,才选择部分特化.

演示.请注意,&in std::declval<std::ostream&>()是重要的,因为否则std::declval<std::ostream>()是一个rvalue,你将获得ostreamcatchall rvalue stream插入操作符,并报告所有内容都是可流式的.

上面的代码检查operator<<可以接受T右值的代码.如果要检查接受左值的那个T,请使用std::declval<T&>().


ere*_*non 4

使用 SFINAE,可以像这样:

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};
};
Run Code Online (Sandbox Code Playgroud)