1

チェーンをサポートするためにconst参照をoperator=返す必要があることはよく知られていますが、これは右辺値が値のようなものとして使用できる場合にのみ機能します。*this*this

編集:問題ありません。constoperator=以外の参照を返す必要があります(ints として実行します)。これは、割り当て*thisで意味のあるものにする必要があることを意味しました。rhs

オーバーロードされた一時的な書き込み専用を返すことで、C++ クラスApiWrapperを介して name=value セッター関数の C API をラップしていますが、API にはゲッター関数がないため、実質的に書き込み専用です。operator[]Proxyoperator=Proxy

ApiWrapper x;
x["a"] = x["b"] = 42;  // x["b"] = 42;      fine:  consumes 42, returns *this
                       // x["a"] = x["b"];  error: x["b"] does not have the value

fromrhsの代わりにconst 参照を返すと、連鎖がうまくいくように思えます。概念的に (プロキシ ボイラープレート コードは省略):*thisoperator=

struct Proxy {
    template <typename T>
    T const& operator=(T const& rhs) const
    {
        ...         // pass rhs to the API but don't store it
        return rhs; // return rhs, not *this
    }
};

ApiWrapper x;
x["a"] = x["b"] = 42;  // x["b"] = 42;   fine: consumes and returns 42
                       // x["a"] = 42;   fine: consumes and returns 42

しかし、これは私を疑わしくさせます。rhsの代わりにconst 参照を返すことによる奇妙な副作用はあり*thisますか? 私が考えられる唯一のことは、次のような式では使用できないということです(x["a"] = 42).doSomething()Proxy、書き込み専用であるため、とにかくそのようなものはサポートできません。それとも、チェーンを許可しない方がよいでしょうか (たとえば、 を返すことによってvoid)?

編集:値のようなものではない場合でも、Proxy代入をサポートすることは理にかなっていると思います。次のような構文糖衣を許可します。

// this:                          // rather than:
ApiWrapper w;                     API * ptr = make_api_instance();
w["name"] = "Batman";             api_set_str(ptr, "name", "Batman");
w["age"]  = 42;                   api_set_int(ptr, "age", 42);
w["pi"]   = 3.14;                 api_set_double(ptr, "pi", 3.14);
4

2 に答える 2

1

最もクリーンな解決策は、標準的な慣用句に固執することだと思います。通常の方法でプロキシ クラスをコピー構築可能かつコピー割り当て可能にすると、これは機能するはずです。このようなもの:

struct Proxy
{
    Proxy(Proxy const & rhs)
    : // ...
    {
        // copy internal state of rhs
    }

    Proxy & operator=(Proxy const & rhs)
    {
        // copy internal state of rhs
        return *this;
    }

    template <typename T>
    Proxy & operator=(T const & rhs)
    {
        // ... perform T-specific operations ... #1
        return *this;
    }
};

追加の利点は、#1 の最初の割り当てで実行する必要がある「一般的なロジック」が、後続のすべての割り当てで繰り返す必要がないことです。

于 2013-05-25T12:08:19.837 に答える
0

あなたのアプローチは理にかなっていると思います。問題を正しく理解しているかどうかを確認するために、構造体は次のようになります。

struct Proxy {
    template <typename T>
    T const& operator=(T const& rhs) const
    {
        send_to_abi(rhs);
        return rhs;
    }
};

rhsあなたが言うように、プロキシはどこにも保存されずreceive_from_abi、関数が存在しないと仮定しているため、戻り値は機能しませ*thisん-この場合、数値は伝播されません。コメントが指摘しているように、 のようないくつかの動作(a=3)=3は機能しませんが、それはそれほど驚くべきことではありません。

編集: コメントが指摘するように、このアプローチはrhs一時的なものであれば危険です。これは、代わりにコピーを返すことで修正できます。

struct Proxy {
    template <typename T>
    T operator=(T const& rhs) const
    {
        send_to_abi(rhs);
        return rhs;
    }
};

a["a"] = a["b"] = a["c"] = fooこれは、3 つのコピーが必要なように見えて高価に見えるかもしれません。しかし、これらは一般的なコンパイラーの最適化によって回避できるはずです。

于 2013-05-25T12:17:07.133 に答える