运算符在命名空间中的类外部重载

时间:2016-06-22 19:48:08

标签: c++

我正在尝试为命名空间中的union类重载比较运算符,以将其用作unordered_map中的键。

x.h:

#include <DirectXPackedVector.h>

namespace std
{
    template<> struct hash<DirectX::PackedVector::XMUBYTEN4>
    {
        std::size_t operator()(DirectX::PackedVector::XMUBYTEN4 const& s) const {
            std::size_t const h1(std::hash<uint8_t>()(s.x));
            std::size_t const h2(std::hash<uint8_t>()(s.y));
            std::size_t const h3(std::hash<uint8_t>()(s.z));
            std::size_t const h4(std::hash<uint8_t>()(s.w));
            return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3);
        }
    };
}

    std::unordered_map<DirectX::PackedVector::XMUBYTEN4, unsigned int> mc_province_index;

散列工作正常,但是当我尝试像这样重载比较运算符时:

bool operator==(const DirectX::PackedVector::XMUBYTEN4 & lhs, const DirectX::PackedVector::XMUBYTEN4 & rhs) {
    if (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w)
        return true;
    return false;
}

我得到了

C2678: binary '==' : no operator found which takes a left-hand operand of type 'const DirectX::PackedVector::XMUBYTEN4' (or there is no acceptable conversion)

我尝试在命名空间

中进行
namespace DirectX{
    namespace PackedVector{
        bool operator==(const DirectX::PackedVector::XMUBYTEN4 & lhs, const DirectX::PackedVector::XMUBYTEN4 & rhs) {
            if (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w)
                return true;
            return false;
        }
    }
}

但是这给了我一个LNK2005,说它已经在目标文件中定义了。

我在这里做错了什么以及如何重载此运算符?

1 个答案:

答案 0 :(得分:2)

您应该将operator==()定义为inline函数(如果存在于头文件中),因为您很可能违反一个定义规则。

http://en.cppreference.com/w/cpp/language/definition [一个定义规则]

  

每个非内联函数或变量的唯一定义   在整个过程中需要使用odr-used(见下文)   程序(包括任何标准和用户定义的库)。该   编译器不需要诊断此违规,但行为   违反它的程序是未定义的。

     

对于内联函数,   每个翻译单元都需要一个定义   ODR使用。

基本上有bug类别如何违反ODR。

  1. 单个编译单元中的多个定义。这就是我们在头文件中使用包含警戒的原因。
  2. 编译单元级别没有违反,但是包含链接在一起的定义的多个编译单元。 (本案例。)
  3. 修复很简单:

    namespace DirectX{
        namespace PackedVector{
            inline bool operator==(const DirectX::PackedVector::XMUBYTEN4 & lhs, const DirectX::PackedVector::XMUBYTEN4 & rhs) {
                if (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w)
                    return true;
                return false;
            }
        }
    }