我正在尝试使用可以处理对称对的模板结构。实现比较运算符以使结构在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"));
可以正常工作。
但是,当模板参数T
和U
相同时,我遇到麻烦(编译时错误),例如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)。
如果还有一种方法可以使结构更加优雅,我很感兴趣。
答案 0 :(得分:3)
我认为最简单的方法是部分专业化,特别是如果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;
};
答案 1 :(得分:0)
我宁愿扩展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>
中使用了这些函数。