2012-12-26 3 views
4

이 질문은 Why does passing object reference arguments to thread function fails to compile?과 관련이있을 수 있습니다.스레드 함수에 인수 전달 (템플릿)

필자와 비슷한 문제가 생겼다. 필자의 경우 functor가 템플릿이다.

class A { 
public: 
    // Non template version works as expected!!. 
    // void operator()(std::ostream& out){ 
    // out << "hi\n"; 
    // } 

    // template version doesn't. 
    template <class Ostream> 
    void operator()(Ostream& out){ 
     out << "hi\n"; 
    } 

}; 

int main() { 
    A a; 
    thread t(a, ref(cout)); 
    t.join(); 
} 

GCC는 말한다 :

error: no match for 'operator<<' in 'out << "hi\012"' 

가 어떻게이 문제를 해결할 수

?

+0

스레드가 인수를 사용하여 무언가를 인쇄하기 때문에 인수가 암시 적으로 인수로 가정합니다. 여기에 템플릿이 정말로 필요합니까? – jogojapan

+0

@ jogojapan :이 템플릿을 함수 템플릿으로 만들려고 한 이유는 boost에서 ostream을 사용해야하기 때문입니다. 부스트/iostreams 및 부스트/파일 시스템. 귀하의 의견을 읽은 후, 나는 boost :: filesystem :: ofstream을 템플릿이 아닌 버전과 함께 전달하려고 시도했으며 작동합니다 !!. 그러나 다른 모든 ostreams에서도 작동하는지 확신 할 수 없습니다. – Sungmin

+0

'std :: ostream'에서 _derived_ 인 모든 것을 처리 할 것입니다. 출력 스트림의 경우에는'std :: ostream'에서 파생시키는 것이 좋습니다. 사용하려는 스트림 유형이'std :: ostream'에서 파생되지 않은 경우를 제외하고는, 내가 너라면,'std :: ostream &'인수를 취하는 것으로 충분하다고 가정한다. – jogojapan

답변

3

std::reference_wrapper을 전달 중입니다. 따라서 class Ostream의 유형은 오류를 설명하는 std::reference_wrapper이됩니다.

template <class OstreamRef> 
void operator()(OstreamRef& outRef){ 
    outRef.get()<< "hi\n"; 
} 

이렇게 수정해야합니다.

템플릿이 아닌 경우 std::ostream&으로 변환해야 할 경우 get()이 암시 적으로 호출됩니다. 그러나 템플릿을 사용하면 다른 형식으로 변환 할 필요가 없기 때문에 std::reference_wrapper은있는 그대로 전달되므로 get()에 대한 명시 적 호출이 필요합니다. 고마워요 @ jogojapan

+0

고마워요. get() 멤버 함수를 처음 접하게됩니다. 즉, 비 템플릿 함수에 대한 참조를 전달하면 get()을 사용할 필요가 없습니다. 그러나 템플릿 함수에 대한 참조를 전달하면 get()을 사용해야합니다. 위의 문장은 일반적으로 보류합니까? – Sungmin

+3

@ 성민 No. 참조가 아닌'std :: reference_wrapper '를 다루기 때문에'get()'이 필요합니다. 함수가 템플릿이 아니지만'std :: ostream &'을 가정하면 참조 래퍼가 자동으로 참조로 변환됩니다 (즉,'get()'이 암시 적으로 호출됩니다). 그러나 템플릿을 사용하면 컴파일러는 템플릿을 인스턴스화 할 때'std :: ostream &'으로 변환 할 이유가 없으므로 참조 래퍼로 남겨 둡니다. 이 솔루션의 문제점 (즉,'get()'을 명시 적으로 호출하는 것)은 참조 래퍼 (ostream이 아닌)를 전달할 때만 작동한다는 것입니다. – jogojapan