英文:
How to check if operator<< is defined for a class?
问题
我想使用类型特征(type traits)来检查某些类是否定义了操作符 <<
。
所以我定义了两个类 A
和 B
,它们很相似,但操作符 <<
只在类 A
中重载了。
为了实现这一目的,我正在使用 boost::is_detected
。
以下是运行的代码:
#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
为什么我得到了相同的结果?
如果你有其他问题或需要进一步的解释,请告诉我。
英文:
I want to use type traits to check if operator <<
is defined for some classes.
So I've defined 2 classes A
and B
which are similar but the operator <<
is overloaded only for A
.
To do that I am making use of boost::is_detected
.
The running code is the following:
#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;
}
However, this is not working and the output I am getting is:
A has operator '<<'? 0
B has operator '<<'? 0
Why am I getting identical results?
答案1
得分: 2
std::ostream& operator<<(std::ostream& destination, const A& type)
是一个自由函数,而不是一个成员函数,只检查成员函数的存在。
你可以重写你的类型特性,以便与成员和非成员输出运算符一起工作,如下所示:
// 假设情况
template <typename T, typename = void>
struct has_operator_insertion_check : std::false_type {};
// 部分特化,如果 std::declval<std::ostream&>() << std::declval<T>() 有效,则为 true
template <typename T>
struct has_operator_insertion_check<T, std::void_t<decltype((std::declval<std::ostream&>() << std::declval<T>()))>> : std::true_type {};
template <typename T>
constexpr bool has_operator_insertion_v = has_operator_insertion_check<T>::value;
你可以在这个 实时示例 中看到它的工作方式。
<details>
<summary>英文:</summary>
std::ostream& operator<<(std::ostream& destination, const A& type)
is a free function, not a member function and
decltype(void(&std::decay_t<T>::operator<<));
only checks for the presence of a member function.
You can rewrite your type trait to work with member and non-member output operators like
// false case
template <typename T, typename = void>
struct has_operator_insertion_check : std::false_type {};
// partial specialization,
// if std::declval<std::ostream&>() << std::declval<T>() is valid then true
template <typename T>
struct has_operator_insertion_check<T, std::void_t<decltype((std::declval<std::ostream&>() << std::declval<T>()))>> : std::true_type {};
template <typename T>
constexpr bool has_operator_insertion_v = has_operator_insertion_check<T>::value;
You can see this working in this [live example][1].
[1]: http://coliru.stacked-crooked.com/a/e751372006b6cd87
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论