7

ベクターをラップするテンプレート化されたクラスがあります。このクラスに unique_ptrs を格納しようとしていますが、正常に動作します。ただし、void add(const T& elem)関数を仮想としてマークすると、コンパイラ (clang) は、unique_ptr に対して「暗黙的に削除されたコピー コンストラクターへの呼び出し」を行っていることを通知します。

unique_ptrs はコピーできないことを理解しているので、void add(T&& elem)関数を作成しました。他の追加関数を仮想としてマークするとコンパイラエラーが発生する理由がわかりません。

御時間ありがとうございます。

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

template <typename T>
class ContainerWrapper {
private:
    vector<T> vec;
public:
    ContainerWrapper() : vec() {

    }

    //Marking this as virtual causes a compiler error
    void add(const T& elem) {
        vec.push_back(elem);
    }

    void add(T&& elem) {
        vec.push_back(std::move(elem));
    }

    T removeLast() {
        T last = std::move(vec.back());
        vec.pop_back();
        return last;
    }
};

int main() {
    ContainerWrapper<unique_ptr<string>> w;
    w.add(unique_ptr<string>(new string("hello")));

    unique_ptr<string> s = w.removeLast();

    cout << *s << endl;
}
4

2 に答える 2

5

ここでの問題は、std::unique_ptrそのコピー コンストラクターが としてマークされていること=deleteです。これは、オーバーロードされたメンバー関数vec.push_back(elem)内の呼び出しは、 . コンパイラは、メンバー関数がインスタンス化されるとすぐにこれを認識します。add(T const&)std::unique_ptr

標準には、 14.7.1 暗黙的なインスタンス化 [temp.inst]に 2 つの関連する引用があります。

6 オーバーロード解決プロセスが、クラス テンプレート定義をインスタンス化せずに呼び出す正しい関数を決定できる場合、そのインスタンス化が実際に行われるかどうかは不明です。

10 [...] 仮想メンバー関数がインスタンス化されない場合、実装がクラステンプレートの仮想メンバー関数を暗黙的にインスタンス化するかどうかは指定されていません。[...]

条項 6 では、キーワードなしvirtualで、コンパイラは許可されていますが、両方をインスタンス化する必要はなく、add(T const&)どちらadd(T&&)のオーバーロードが最適であるかを解決する必要はありません。gcc 4.7.2 も Clang 3.2 もインスタンス化を必要としません。なぜなら、右辺値参照は常に左辺値参照よりも一時変数に適していると推測するからです。

条項 10 では、キーワードを使用してvirtualも、コンパイラもインスタンス化する必要はありませんがadd(T const&)add(T&&)どのオーバーロードが最適かを解決するために使用できると述べています。gcc 4.7.2 と Clang 3.2 の両方が、左辺値のオーバーロードがより適切に一致することは決してないと推測できたとしても、両方のメンバー関数をインスタンス化します。

ContainerWrapperネストされた で通常のクラスを作成すると、両方のメンバー関数のコードを生成する必要があるためtypedef unique_ptr<string> T;、キーワードの有無にかかわらず、gcc と Clang の両方でエラーが生成されることに注意してください。virtual推定された引数の置換中にエラーが発生しないため、これは SFINAE で取り除かれません。

結論: これはバグではなく、実装の品質の問題です。

于 2013-01-28T12:41:52.693 に答える