首页 > 解决方案 > 运算符<在 std::pair 上重新定义在课堂模板中

问题描述

我在类模板案例中遇到以下情况:

template<class T1,class T2>
class targetClass{

public:

    typedef typename std::pair<T1, T2> ToSortType;
    typedef typename std::set<ToSortType> ContainerSort;  

    void bar(ToSortType a, ToSortType b);

private:

    ContainerSort container;
    bool operator<(const ToSortType& rhs) const;

}

template<class T1,class T2>
void targetClass<T1,T2>::bar(ToSortType a, ToSortType b){

    container.insert(a);
    container.insert(b);

}

template <class T1,class T2>
bool targetClass<T1,T2>::operator<(const ToSortType& rhs) const
{
    return this->first < rhs.first;
}

在主函数中是这样的:

targetClass<int,T2> anObjectTarget;
T2 a;
T2 b;
anObjectTarget.bar(std::make_pair(0,a),std::make_pair(1,b));

T2通常没有定义的operator< 用户定义类型在哪里?在这种情况下,编译器无法为. 在前面的代码片段中,我重新定义了相关的运算符,但编译器以这种方式抱怨:std::setstd::pair<int,T2>operator<intT2T2

/usr/include/c++/7/bits/stl_pair.h:456: error: no match for ‘operator<’ (operand types are ‘const T2’ and ‘const T2’)
       || (!(__y.first < __x.first) && __x.second < __y.second); }
                                       ~~~~~~~~~~~^~~~~~~~~~~~  

我以前从未重新定义过运算符,但查看文档对我来说是正确的(但不是编译器)。

标签: c++templatesoperator-overloading

解决方案


您重载的运算符是其中的一个成员,targetClass<T1,T2>并将两个ToSortType作为参数。这不是<运算符重载的工作方式。考虑到对于类类型的实例,以下两个是等价的:

 a < b
 a.operator<(b)

即运算符只是调用特殊成员函数的语法糖。您编写的运算符只能称为

 targetClass<T1,T2> t;
 T1 a;
 T2 b;
 t.operator<(a,b);

但是该集合试图调用的是a < b,即a.operator(b)显然不存在(std::pair<T1,T2>只能通过<when both T1and T2can)。

长话短说:您不能使用运算符来比较ToSortType.

我不建议尝试重载operator<for std::pair<T1,T2>,而是使用自定义类型:

template<class T1,class T2>
class targetClass{

public:
    struct value_type {
        T1 first;
        T2 second;
        bool operator<(const value_type& other) {
             return first < rhs.first;
        }
    }
    using container_type = std::set<value_type>;    
    void bar(const value_type& a,const value_type& b);    
private:    
    container_type container;    
};

如果您想留下来,那么您可以使用允许您选择比较器类型的std::pair事实。std::set但是,首先我必须解释一下以免使您感到困惑,因为以下内容似乎与上述内容相矛盾(事实并非如此)。set 使用的默认比较器是std::less<Key>,这是一个类型,operator()它比较两个类型的元素Key,它类似于(但不完全是)这样的:

template <typename Key>
struct less {
    bool operator() (const Key& a,const Key& b) const {
        return a < b;
    }
};

这是编译器无法<为您的Key类型(即std::pair<T1,T2>)找到 a 的地方。您可以使用自己的比较器:

template <typename T1,typename T2>
struct my_comparator {
     bool operator() (const std::pair<T1,T2>& a, const std::pair<T1,T2>& b) const {
         return a.first < b.first;
     }
};

然后你的设置是

using container_type = std::set<typename std::pair<T1,T2>,typename my_comparator<T1,T2>>;

推荐阅读