因此,使用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());
}
或沿着那条线的东西。
我的问题是......如何做同样的事情,但对于非成员函数?
特别是我试图检查是否存在以下情况:
operator<<(std::ostream& os, X& whateverclass);
存在。有可能测试吗?
编辑:问题与:Is it possible to write a template to check for a function's existence?不同,我试图查看函数是否存在,而不是方法
答案 0 :(得分: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 {};
当且仅当表达式格式正确时才选择部分特化。
Demo。
请注意,&
中的std::declval<std::ostream&>()
非常重要,因为否则std::declval<std::ostream>()
是一个左值,您将获得ostream
的捕获右值流插入运算符,并报告一切都是可流动的。
以上代码检查可以接受operator<<
右值的T
。如果您想检查接受左值T
的广告,请使用std::declval<T&>()
。
答案 1 :(得分: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};
};