2

我遇到了这个问题:

// A.h
#include <vector>
typedef std::vector<unsigned char> Buffer;
Buffer &operator+=(Buffer &a, Buffer const &b);

// B.h
namespace Bar
{
     struct Qux { };
     Qux &operator+=(Qux &a, Qux const &b);
}

// Foo.cpp
#include "A.h"
#include "B.h"      // comment this out, error goes away

namespace Bar
{
    void foo()
    {
        Buffer a, b;
        a += b;       // error
    }
 }

问题(如here所述)是因为隐藏而a += b;无法编译;而 ADL 没有找到,因为 ADL 只在这种情况下搜索。Bar::operator+=(Qux&, Qux const &)::operator+=::operator+namespace std;

这很棘手,因为问题仅在包含时才会出现B.h- 但B.h显然与Buffer. 代码不应该根据我是否包含另一个标题而中断。

(实际上我只是在更改编译器时才发现这一点,我使用的以前的编译器确实名称查找错误并接受了代码)。

我的问题是:A.h由于这个问题,过载只是一个坏主意吗?

我现在通过在里面B.h做来解决这个问题,但这似乎很hacky,有更好的选择吗?using ::operator+=;namespace Bar

4

2 回答 2

2

虽然我不确定在这种情况下运算符重载是否风格不好,(如您所知,这可能是一个有争议的问题),但这似乎是“函数范围”的问题,而不是“运算符”的问题'。即使将 'operator+=()' 更改为 'Add()',也可能得到相同的结果。

在这种情况下,运算符重载是否具有不良风格与问题无关。

于 2014-06-03T00:57:40.163 回答
2

我能想到的最简单、最安全、最可重用的方法是让+=参数之一是运算符命名空间中的一种类型:

template <typename T>
struct ArgumentRef
{
    ArgumentRef(T& t) : t_(t) { }
    operator T&() { return t_; }
    operator const T&() const { return t_; }
    T& t_;
};

typedef std::vector<unsigned char> Buffer;
Buffer &operator+=(ArgumentRef<Buffer> a, Buffer const &b) { }

也就是说,继承 - 虽然由于非虚拟析构函数在 C++ 圈子中存在争议vector- 恕我直言,尤其是如果您没有Buffer在 API 中公开以供更广泛使用,并且没有在也设计为拥有的代码中使用动态分配的实例并处理基类。

于 2014-06-03T00:40:01.167 回答