c++ - 模板运算符<未调用

标签 c++ templates operator-overloading template-specialization

以下代码实现模板类Data其目的是比较其成员对象。目的是如果成员对象属于同一类型,则该对象的 operator<用于比较,如果成员对象是不同类型,std::stringoperator<用于成员对象的字符串化。

#include <iostream>
#include <sstream>

template <typename T>
class Data
{
public:
  Data( const T& t ) : m_data( t ) {}
  template <typename U> bool operator<( const Data<U>& cu )
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    return ( static_cast<std::ostringstream&>(( std::ostringstream().flush() << m_data )).str() <
             static_cast<std::ostringstream&>(( std::ostringstream().flush() << cu.m_data )).str() );
  }

#if 1 // Change this to "#if 0" and code doesn't work anymore.
  bool operator<( const Data<T>& ct )
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    return ( m_data < ct.m_data );
  }
#endif

private:
  T m_data;
  template< typename U> friend class Data;

friend bool operator< <T> ( const Data<T>&, const Data<T>& );
};

template<typename T>
bool operator<( const Data<T>& a, const Data<T>& b )
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  return ( a.m_data < b.m_data );
}

int main( int argc, char* argv[] )
{
  Data<int> a(10);
  Data<std::string> b("2");
  Data<int> c(2);
  std::cout << "10 < \"2\"? " << std::boolalpha << ( a < b ) << std::endl;
  std::cout << "10 < 2? " << std::boolalpha << ( a < c ) << std::endl;
  return 0;
}

我正在试验一个成员 operator<()与全局范围内的 operator<() 相比.前者在 #if 1 中展示。 block ,并按预期工作。当我试图通过更改 #if 1 来强制使用后者时至 #if 0 ,代码不再按预期运行:全局范围 operator<()似乎没有被调用。

有人可以指出为什么全局范围的 operator<()未被调用/不起作用,而成员 operator<()是吗?

最佳答案

这里发生的是什么@n.m. said in the comments .我花了一段时间才找到发生这种情况的确切原因,尽管最后很简单。

当您考虑运算符重载时,会生成一个可行函数列表,然后将其传递给算法,该算法确定将调用其中的哪些函数。特别是对于运算符重载所考虑的函数列表是这样的

16.3.1.2 表达式中的运算符 [over.match.oper/6]

The set of candidate functions for overload resolution is the union of the member candidates, the non-member candidates, and the built-in candidates.

cppreference explains it in more detail

For a unary operator @ whose argument has type T1 (after removing cv-qualifications), or binary operator @ whose left operand has type T1 and right operand of type T2 (after removing cv-qualifications), three sets of candidate functions are prepared:

1) member candidates:

2) non-member candidates:

3) built-in candidates:

当重载决议发生时,成员函数会发生一些特殊的事情(强调我的)

If any candidate function is a member function (static or non-static), but not a constructor, it is treated as if it has an extra parameter (implicit object parameter) which represents the object for which they are called and appears before the first of the actual parameters.

所以本质上,你为你的案例获得的重载是

template <typename U> 
bool operator<(EXACT_TYPE_PTR this, const Data<U>& cu );
template<typename T>
bool operator<(const Data<T>& a, const Data<T>& b)

在哪里EXACT_TYPE_PTR被您决定调用的任何对象的类型替换 operator<在。现在您有两个候选对象,一个是模板,另一个接受一个模板参数和一个模板实参。所以自然地,具有精确类型的那个是首选,因为它是一个精确匹配


注意 您可能应该将成员设置为 operator<() function const,这样它可以更通用,甚至可以接受 const 参数。在当前情况下,如果您有 const Data实例,那么将调用非成员重载

关于c++ - 模板运算符<未调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44795721/

相关文章:

c++ - 可以给 `std`命名空间添加推导指南吗?

azure - 有没有办法在 Azure DevOps 发行说明中对工作项类型进行排序/分组

c++ - 当它是模板参数时默认成员变量指针

c++ - 在 C++ 中重载 [] 以返回左值

c++ - 重载级联插入运算符

c++/boost program_options 一个选项禁用其他

c++ - C++逐行复制

c++ - 链表析构函数

C++奇怪的模板问题

c++ - 如何强制 operator>>(C<T>) 重载以匹配容器?