2016-12-20 1 views
3

, 다음 코드는이 오류의 원인은? here에서 예를 들어 보면&&는 언제 '전달 참조'를 의미합니까?</p> <blockquote> <p>'Container::Wrapper::Wrapper(S)': member function already defined or declared</p> </blockquote> <p>컴파일러가 <code>Wrapper</code>의 생성자에서 <code>S&&</code> 생각 하는가 전달 참조는 다음과 같습니다 컴파일 할 때

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 추론 된 '자동'유형 일 수도 있습니다. – KABoissonneault

+0

'Wrapper (S && ​​obj)'의'S'는 생성자를 호출 할 때 오직'Wrapper '객체를 정의 할 때만 추론됩니다. 따라서 전달 참조가 아닌 rvalue 참조입니다. – KABoissonneault

답변

2

Wrapper 구현과 관련된 범용 참조가 없습니다. 코드에서 유일한 범용 참조는 Container<>::push_back의 매개 변수입니다.

cont.push_back(foobar);을 호출하면 S의 매개 변수 은 Foobar &으로 추정됩니다.

나중에 Wrapper<S>S == Foobar &으로 인스턴스화하려고 시도했습니다. 참조 축소 규칙에 따라 Wrapper의 생성자 매개 변수 선언 S &&Foobar &으로 변경되고 const S &Foobar &이됩니다.

이것은 동일한 서명이있는 두 개의 "오버로드 된"Wrapper::Wrapper 생성자로 끝나는 것을 의미합니다. 이것은 사용자가 관찰 한 오류 메시지의 원인입니다.

std::vector을 lvalue 참조 유형의 템플릿 인수로 인스턴스화하려고하면 정확히 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

좋아 ... 지금 더 의미가 있습니다. 'assert (std :: is_same :: value)'는 (assert (std :: is_same :: value)'을 처리하고 있다고 생각했던 곳에 push_back 본문을 전달합니다. – bitwise