2
union word{
    uint16_t value;

    struct{
        uint8_t low;
        uint8_t high;
    };


    inline  word(uint16_t value) noexcept
        :value(value)
    {}


    inline word &operator=(uint16_t rhs) noexcept{
        value = rhs;
        return *this;
    }

    inline operator uint16_t() const noexcept{
        return value;
    }
}

下位バイトと上位バイトに簡単にアクセスできるリトルエンディアンの 2 バイト型を定義しようとしています。さらに、算術演算子を呼び出すときに、「単語」型が完全に uint16_t のように動作するようにします。したがって、uint16_t の型キャスト演算子をオーバーロードしました。

しかし、私はわずかな問題に遭遇しました:

word w1 = 5;
w1 = w1 + w1;  //this works fine due to implicit conversion
w1 += w1; //fails to compile.  lhs will not implicitly convert

コンパイルに失敗する理由がわかりました。+=、-=、&=、|= などのすべての算術演算子のオーバーロードを回避したいのですが、すべての演算子を定義する必要を回避する方法はありますか? それらのほとんどが必要になる可能性があります。

どうもありがとうございました!

4

1 に答える 1

1

問題は次の行にあります。

inline operator uint16_t() const noexcept{
   return value;
}

あなたがするとき

w1 += w1;

左手w1は暗黙的に に変換されuint16_tます。ただし、実際には、変換の結果として一時オブジェクトであるコピーを返しています。w1.valueまた、一時的なオブジェクトに割り当てることはできません。そして、魔法のようにできる場合、変更は に反映されw1.valueません。これは望ましくないことです。

あなたの問題を解決するには、代わりに の参照を返しvalue、変換関数を notにします。絶対に変更可能にしconstたいからです。value

inline operator uint16_t&() noexcept{
   return value;
}

これは、ソリューションが機能することを示す実際の例です。


ただし、この質問を読むことをお勧めします:演算子のオーバーロード

クラスの演算子を明示的にオーバーロードすると、暗黙の変換に依存するよりもはるかに安全で予測可能になります。暗黙の変換は、時々奇妙な結果をもたらし、エラーをコンパイルします。

于 2013-08-23T06:13:03.963 に答える