用于双和单类型的泛型对称对c++

Generic symmetric pair c++ for double and single types

本文关键字:泛型 对称 c++ 类型 单类型 用于      更新时间:2023-10-16

我试图有一个模板结构,可以处理对称对。实现比较操作符是为了使结构体在std::map中工作。

到目前为止,我使用以下代码:
template<typename T, typename U>
struct SymmetricPair
{
    SymmetricPair() : m_id(std::pair<T,U>()) {}
    SymmetricPair(const SymmetricPair<T,U>& id) : m_id(id) {}
    SymmetricPair(const SymmetricPair<U,T>& id) : SymmetricPair(id.m_id) {}
    SymmetricPair(const std::pair<T,U>& id) : m_id(id) {}
    SymmetricPair(const std::pair<U,T>& id) : m_id(std::pair<T,U>(id.second,id.first)) {}
    SymmetricPair(const T id_t, const U id_u) : m_id(std::pair<T,U>(id_t, id_u)) {}
    SymmetricPair(const U id_u, const T id_t) : m_id(std::pair<T,U>(id_t, id_u)) {
    bool operator< (const SymmetricPair<T,U>& rhs) const { return m_id <  rhs.m_id; }
    bool operator!=(const SymmetricPair<T,U>& rhs) const { return m_id != rhs.m_id; }
    bool operator==(const SymmetricPair<T,U>& rhs) const { return m_id == rhs.m_id; }
    bool operator< (const SymmetricPair<U,T>& rhs) const { return m_id <  SymmetricPair<T,U>(rhs.m_id).m_id; }
    bool operator!=(const SymmetricPair<U,T>& rhs) const { return m_id != SymmetricPair<T,U>(rhs.m_id).m_id; }
    bool operator==(const SymmetricPair<U,T>& rhs) const { return m_id == SymmetricPair<T,U>(rhs.m_id).m_id; }
    std::pair<T,U> m_id;
};

例如使用SymmetricPair<std::string,int> pair(std::pair<int,std::string>(42,"bde"));就可以。

然而,当模板参数TU相同时,我有麻烦(编译时错误),例如SymmetricPair<std::string,std::string>,因为一些操作被认为已经定义

'SymmetricPair<T,U>::SymmetricPair(const SymmetricPair<T,U> &)' : member function already defined or declared   
'SymmetricPair<T,U>::SymmetricPair(const std::pair<_Ty1,_Ty2> &)' : member function already defined or declared 
'SymmetricPair<T,U>::SymmetricPair(const T,const U)' : member function already defined or declared
'bool SymmetricPair<T,U>::operator <(const SymmetricPair<T,U> &) const' : member function already defined or declared   
 'bool SymmetricPair<T,U>::operator !=(const SymmetricPair<T,U> &) const' : member function already defined or declared 
'bool SymmetricPair<T,U>::operator ==(const SymmetricPair<T,U> &) const' : member function already defined or declared  

我怎样才能解决这个问题?我使用vc++ 2005(所以没有c++ 11)。

如果还有一种方法可以使结构更优雅,我很感兴趣。

我认为最简单的方法是部分专门化,特别是在c++ 11不可用的情况下:

template<typename T>
struct SymmetricPair<T, T>
{
    SymmetricPair() : m_id() {}
    SymmetricPair(const SymmetricPair& id) : m_id(id.m_id) {}
    SymmetricPair(const std::pair<T,T>& id) : m_id(id) {}
    SymmetricPair(const T id_t, const T id_u) : m_id(id_t, id_u) {}
    bool operator< (const SymmetricPair<T,T>& rhs) const { return m_id <  rhs.m_id; }
    bool operator!=(const SymmetricPair<T,T>& rhs) const { return m_id != rhs.m_id; }
    bool operator==(const SymmetricPair<T,T>& rhs) const { return m_id == rhs.m_id; }
    std::pair<T,T> m_id;
};

我宁愿扩展pair,或者在特定情况下使用不同的相等操作符和哈希操作符。

我刚刚写了这个类:

/** Copyright (C) 2016 Ultimaker - Released under terms of the AGPLv3 License */
#ifndef UTILS_SYMMETRIC_PAIR
#define UTILS_SYMMETRIC_PAIR
#include <utility> // pair
namespace cura 
{
/*!
* A utility class for a pair of which the order between the first and the second doesn't matter.
* 
* tparam A The type of both elements of the pair.
*/
template<class A>
class SymmetricPair : public std::pair<A, A>
{
public:
    /*!
    * Forwarding std::pair constructor
    */
    template<class U>
    SymmetricPair(const SymmetricPair<U>& pr)
    : std::pair<A, A>(pr)
    {
    }
    /*!
    * Forwarding std::pair constructor
    */
    template<class U>
    SymmetricPair(SymmetricPair<U>&& pr)
    : std::pair<A, A>(pr)
    {
    }
    /*!
    * Forwarding std::pair constructor
    */
    SymmetricPair(const A& first, const A& second)
    : std::pair<A, A>(first, second)
    {
    }
    /*!
    * Forwarding std::pair constructor
    */
    template<class U>
    SymmetricPair(U&& first, U&& second)
    : std::pair<A, A>(first, second)
    {
    }
    /*!
    * Forwarding std::pair constructor
    */
    template <class... Args1, class... Args2>
    SymmetricPair(std::piecewise_construct_t pwc, std::tuple<Args1...> first_args, std::tuple<Args2...> second_args)
    : std::pair<A, A>(pwc, first_args, second_args)
    {
    }
    /*!
    * Equality operator which checks if two SymmetricPairs are equal regardless of the order between first and second
    */
    bool operator==(const SymmetricPair& other) const
    {
        return (std::pair<A, A>::first == other.first && std::pair<A, A>::second == other.second) || (std::pair<A, A>::first == other.second && std::pair<A, A>::second == other.first);
    }
};
}//namespace cura
namespace std
{
/*!
* Hash operator which creates a hash regardless of the order between first and second
*/
template<class A>
struct hash<cura::SymmetricPair<A>>
{
    size_t operator()(const cura::SymmetricPair<A>& pr) const
    { // has to be symmetric wrt a and b!
        return std::hash<A>()(pr.first) + std::hash<A>()(pr.second);
    }
};
}//namespace std

#endif // UTILS_SYMMETRIC_PAIR

在其他情况下,我简单地定义了一个单独的等式和哈希函数,并使用它们,例如在unordered_map<Key, Value, MyHasher, MyEquality>中。