2016-12-20 9 views
3

コンパイルすると、次のコードは、このエラーが発生します。&&の意味はいつも '転送参照'ですか?

'Container::Wrapper::Wrapper(S)': member function already defined or declared

は、コンパイラがWrapperのコンストラクタでS&&が転送リファレンスだと思いますか? hereからの例を見てみると

template<typename T> 
struct Container 
{ 
    template<class S> 
    struct Wrapper { 
     S obj; 
     Wrapper(S&& obj) : obj(std::forward<S>(obj)){} 
     Wrapper(const S& obj) : obj(obj){} 
    }; 

    template<class S> 
    void push_back(S&& obj) { 
     void *storage = malloc(sizeof(Wrapper<S>)); 
     new (storage) Wrapper<S>(std::forward<S>(obj)); 
    } 
}; 

struct Foobar{}; 

int main() 
{ 
    Container<Foobar> cont; 
    Foobar foobar; 
    cont.push_back(foobar); 
    return 0; 
} 

、私は私がやっていることは何が違うのですか理解していない:

template <class T, class Allocator = allocator<T> > 
class vector { 
public: 
    ... 
    void push_back(T&& x);  // fully specified parameter type ⇒ no type deduction; 
    ...       // && ≡ rvalue reference 
}; 


編集: この問題を解決するには、にしましたpush_backを変更して、Wrapperをインスタンス化するために使用されている型から参照を削除します。

template<class S> 
void push_back(S&& obj) { 
    typedef std::remove_reference<S>::type U; 
    void *storage = malloc(sizeof(Wrapper<U>)); 
    new (storage) Wrapper<U>(std::forward<S>(obj)); 
} 
+5

"Universal"リファレンスは*推定*テンプレートパラメータを使用する必要があります。 –

+1

標準用語は現在_forwarding_参照です。 @KerrekSBそれは、推測された 'auto'型でもあります。 – KABoissonneault

+0

'Wrapper(S && obj)'の 'S'は、' Wrapper 'というオブジェクトを定義するときにのみ、コンストラクタの呼び出し時に導かれません。したがって、これは正参照であり、転送参照ではありません。 – KABoissonneault

答えて

2

Wrapperの実装に関する普遍的な参照はありません。あなたのコードの唯一の普遍的な参照はContainer<>::push_backのパラメータです。

cont.push_back(foobar);を呼び出すと、Spush_backFoobar &と推定されます。

後でWrapper<S>S == Foobar &でインスタンス化しようとしました。参照の折りたたみルールは、Wrapperのコンストラクタパラメータ宣言でS &&Foobar &になり、const S &Foobar &になることを指示します。

これは、同じシグネチャを持つ2つの "オーバーロードされた" Wrapper::Wrapperコンストラクタで終わることを意味します。これは、エラーメッセージが表示される理由です。

テンプレート引数のlvalue参照型を使用してstd::vectorをインスタンス化しようとすると、正確に同じ問題が発生して、push_backオーバーロードが発生します。しかし、このような試みでは、通常、他の理由でコンパイルに失敗することがあります。その前に、あふれた部分がpush_backになります。

template <typename T> struct MyVector { 
    void foo(T &&) {} 
    void foo(const T &) {} 
}; 

int main() { 
    MyVector<int &> v; 
} 

に続き、同じエラーが生成されますよう

より蒸留例が見えます。

const T &T = U &が実際にはU &となり、const U &ではありません。しかし、それは確かに事実です。

+0

Ok ...今より意味をなさない。 'assert(std :: is_same :: value)'は、私が 'assert(std :: is_same :: value)'を扱っていると思った場所(push_backの本体の中)を渡します。 – bitwise

関連する問題