如何检查类是否定义了`operator<<`?

huangapple go评论125阅读模式
英文:

How to check if operator<< is defined for a class?

问题

我想使用类型特征(type traits)来检查某些类是否定义了操作符 <<

所以我定义了两个类 AB,它们很相似,但操作符 << 只在类 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 &lt;&lt; is defined for some classes.

So I've defined 2 classes A and B which are similar but the operator &lt;&lt; is overloaded only for A.

To do that I am making use of boost::is_detected.

The running code is the following:

#include&lt;iostream&gt;
#include &lt;boost/type_traits/is_detected.hpp&gt;
class A
{
  public:
    std::string name;
    int64_t age;
    bool b;

};

class B
{
  public:
    std::string name;
    int64_t age;
    bool b;

};

std::ostream&amp; operator&lt;&lt;(std::ostream&amp; destination, const A&amp; type)
{
    return destination &lt;&lt; &quot;name=&quot; &lt;&lt; type.name &lt;&lt; &quot;, age=&quot; &lt;&lt; int(type.age)&lt;&lt;std::endl;
}


template &lt;typename T&gt;
using has_operator_insertion_check = decltype(void(&amp;std::decay_t&lt;T&gt;::operator&lt;&lt;));

template &lt;typename T&gt;
using has_operator_insertion = boost::is_detected&lt;has_operator_insertion_check, T&gt;;

template &lt;typename T&gt;
constexpr bool has_operator_insertion_v = has_operator_insertion&lt;T&gt;::value;


int main()
{
  A a, b;
  a.name = &quot;Ciaooooo&quot;;
  a.age = 65536;
  a.b = true;
  std::cout&lt;&lt;&quot;A has operator &#39;&lt;&lt;&#39;? &quot;&lt;&lt;has_operator_insertion_v&lt;A&gt;&lt;&lt;std::endl;
  std::cout&lt;&lt;&quot;B has operator &#39;&lt;&lt;&#39;? &quot;&lt;&lt;has_operator_insertion_v&lt;B&gt;&lt;&lt;std::endl;

  return 0;
}

However, this is not working and the output I am getting is:

A has operator &#39;&lt;&lt;&#39;? 0
B has operator &#39;&lt;&lt;&#39;? 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>



huangapple
  • 本文由 发表于 2023年3月9日 23:45:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75686935.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定