如何检测C++类是否定义operator<<?为何检测结果均为0?
问题:为何检测全局
operator<<的type traits返回false? 我想用type traits检测类是否定义了operator<<运算符,定义了结构相似的类A和B,只为A重载了全局的operator<<。用boost::is_detected实现检测逻辑,但运行后A和B的检测结果都为false。
代码如下:
#include<iostream> #include <boost/type_traits/is_detected.hpp> class A { public: std::string name; int64_t age; bool b; }; class B { public: std::string name; int64_t age; bool b; }; std::ostream& operator<<(std::ostream& destination, const A& type) { return destination << "name=" << type.name << ", age=" << int(type.age)<<std::endl; } template <typename T> using has_operator_insertion_check = decltype(void(&std::decay_t<T>::operator<<)); template <typename T> using has_operator_insertion = boost::is_detected<has_operator_insertion_check, T>; template <typename T> constexpr bool has_operator_insertion_v = has_operator_insertion<T>::value; int main() { A a, b; a.name = "Ciaooooo"; a.age = 65536; a.b = true; std::cout<<"A has operator '<<'? "<<has_operator_insertion_v<A><<std::endl; std::cout<<"B has operator '<<'? "<<has_operator_insertion_v<B><<std::endl; return 0; }
运行输出:
A has operator '<<'? 0 B has operator '<<'? 0
解答
你的检测逻辑完全错误:
- 你写的
has_operator_insertion_check是在检查类的成员函数operator<<,但你给A定义的是全局非成员版本的operator<<,所以这个检测永远不会命中。 - 不管是A还是B,都没有定义成员版的
operator<<,所以检测结果自然都是false。
正确的检测方式应该模拟std::ostream << T这个表达式是否合法,修改检测模板如下:
// 正确的检测表达式:模拟std::cout << T对象的操作 template <typename T> using has_operator_insertion_check = decltype(std::declval<std::ostream&>() << std::declval<const T&>()); template <typename T> using has_operator_insertion = boost::is_detected<has_operator_insertion_check, T>; template <typename T> constexpr bool has_operator_insertion_v = has_operator_insertion<T>::value;
修改后运行,就能得到正确结果:
A has operator '<<'? 1 B has operator '<<'? 0
原理说明:
std::declval<std::ostream&>()用来获取一个std::ostream的左值引用,不需要实际创建对象。std::declval<const T&>()获取const T的左值引用,匹配你定义的全局operator<<的参数类型。- 整个
decltype表达式会检查ostream& << const T&是否合法,合法则检测为true,否则为false。
内容的提问来源于stack exchange,提问作者roschach
相关产品推荐
相关产品推荐

