2012-12-26 58 views
4

此问题可能与Why does passing object reference arguments to thread function fails to compile?有关。将参数传递给线程函数(模板化)

但是,我遇到了类似的问题,在我的情况下,仿函数是一个模板。

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

由于线程使用参数打印的东西,它似乎隐含地假设参数是一个ostream。这里真的需要一个模板吗? – jogojapan

+0

@jogojapan:我试图把它作为一个函数模板的原因是我需要也使用boost中的一些ostreams。升压/ iostreams和升压/文件系统。阅读你的评论后,我试图通过boost :: filesystem :: ofstream与非模板版本,它的作品!但我不确定它是否适用于所有其他ostreams。 – Sungmin

+0

它适用于从'std :: ostream'开始的任何事情。对于输出流,从'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

@Sungmin号你需要'get()',因为你正在处理一个'std :: reference_wrapper'而不是一个引用。如果你的函数不是一个模板,而是假设一个'std :: ostream&',则引用包装器将自动转换为一个引用(即'get()'将被隐式调用)。但是对于模板,编译器在实例化模板时没有理由将其转换为'std :: ostream&',因此它将其作为引用包装。这个解决方案的问题(即明确调用'get()')是只在你传入一个引用包装器(而不是'ostream&')时才起作用。 – jogojapan