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
    }
 }

問題 (ここで説明されているように) は、hides がa += b;原因でコンパイルに失敗することです。この場合、 ADL は検索のみを行うため、ADL は検索しません。Bar::operator+=(Qux&, Qux const &)::operator+=::operator+namespace std;

B.hが含まれている場合にのみ問題が発生するため、これはやっかいB.hですBuffer。別のヘッダーを含めるかどうかに応じて、コードが壊れることはありません。

(実際には、コンパイラを変更したときにのみこれを発見しました。使用していた以前のコンパイラは、名前の検索を誤って実行し、コードを受け入れました)。

私の質問は:A.hこの問題のために過負荷は悪い考えですか?

内部でB.h行うことで今のところ問題を回避していますが、これはかなりハックなようです。より良いオプションはありますか?using ::operator+=;namespace Bar

4

2 に答える 2

2

私が考えることができる最も簡単で、最も安全で、最も再利用可能なアプローチは、+=引数の 1 つを演算子の名前空間の型にすることです。

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++ サークルでは物議をかもしていますが - 特に、より広く使用するために API でvector公開していない場合や、所有するように設計されたコードで動的に割り当てられたインスタンスを使用していない場合は、私見としては問題ありません。Buffer基本クラスを処理します。

于 2014-06-03T00:40:01.167 に答える
2

この場合の演算子のオーバーロードが悪いスタイルであるかどうかはわかりませんが (ご存知のように、議論の余地のある問題かもしれません)、「演算子」の問題ではなく、「関数のスコープ」の問題のようです。 '。「operator+=()」を「Add()」に変更しても、同じ結果が得られる場合があります。

この場合の演算子のオーバーロードのスタイルが悪いかどうかは問題とは関係ありません。

于 2014-06-03T00:57:40.163 に答える