C++のオーバーロード解決について質問です。左辺値と右辺値参照の差のみしか存在しない関数は区別されませんか?

投稿者: Anonymous

例えば以下のようなコードです

class hoge{
    std::vector<int> val;
    hoge(std::vector<int> val) : hoge(std::move(val)){}
    hoge(std::vector<int> && val) : val(std::move(val)){/* 処理 */}
};

以上のコードをgcc(g++ -std=c++17)でコンパイルした所エラーとなりました。
このような関数はオーバーロード解決できないのでしょうか?

また、余談ではありますが、代替として以下のような実装を考えています。
このような実装を代替として用いるのは正しいでしょうか?

class hoge{
    std::vector<int> val;
    hoge(const std::vector<int> & val) : hoge(std::move(std::vector(val))){}
    hoge(std::vector<int> && val) : val(std::move(val)){/* 処理 */}
};

解決

質問にあるような「コンストラクタに渡された値をメンバ変数に格納するだけ」パターンでは、値渡し(pass-by-value)を用いることもできます。オブジェクトのムーブ操作が十分軽量であることを前提として、コンストラクタ引数を左辺値参照(cosnt T&)/右辺値参照(T&&)でオーバロードする必要がなくなるため、コンストラクタへの引数個数が多いときに効果的です。

class hoge{
    std::vector<int> val;
    hoge(std::vector<int> val) : val(std::move(val)){/* 処理 */}
};

C++ソースコード整形ツール Clang-Tidy では modernize-pass-by-value でこのようなソースコード変形をサポートします。

下記記事もご参考に:


値渡しのみ(T) と 左辺値参照(cosnt T&)+右辺値参照(T&&)オーバーロード は、トレードオフ関係にあります。前者ではムーブコンストラクタ呼び出し回数が増えることは間違いありません。極限まで実行時オーバーヘッドを気にするのであれば、元の kizul さん方針の通りオーバーロード方式を維持すればよいと思います。

https://wandbox.org/permlink/nrR9PpFXo1p0r07E

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *