以下代码最能证明我的问题:
#include <fstream>
#include <iterator>
class Bar
{
public: template <class Iterator> Bar(Iterator first, Iterator last) {}
};
void foo(const Bar& bar) { }
int main(int argc, char** argv)
{
std::ifstream file("file.txt");
Bar bar(std::istream_iterator<char>(file), std::istream_iterator<char>());
foo(bar); // error C2664: 'foo' : cannot convert parameter 1 from 'Bar (__cdecl *)(std::istream_iterator<_Ty>,std::istream_iterator<_Ty> (__cdecl *)(void))' to 'const Bar &'
// with
// [
// _Ty=char
// ]
// Reason: cannot convert from 'overloaded-function' to 'const Bar'
// No constructor could take the source type, or constructor overload resolution was ambiguous
return 0;
};
以下是bar
的一些类似的实例,它们不会导致相同的歧义:
Bar bar = Bar(std::istream_iterator<char>(file), std::istream_iterator<char>());
和
std::istream_iterator<char> start(file);
std::istream_iterator<char> end;
Bar bar(start, end);
我的问题是,bar
的第一个声明是什么导致它被误解?
注意:我正在使用Visual Studio 2010(10.0.30319.1)进行测试
答案 0 :(得分:2)
我认为这与你在Meyer的Effective STL书中找到的“C ++最令人烦恼的解析”有关。
Bar bar(std::istream_iterator< char >(file), std::istream_iterator < char >());
被视为**函数声明。**
由于你在foo(bar);
发送一个函数指针而不是:)
如下所示将没有错误:
Bar bar = Bar(//your arguments here);
foo(bar);
答案 1 :(得分:2)
ArunMu获得了部分功劳,它确实是Most Vexing Parse的一个例子,但是这个术语是在Meyer的有效STL(第1章,第6项)中创造的,而非Exceptional C ++。
是被解释为一个函数指针(错误的(__cdecl *)
部分是死的),显然C ++标准要求它以这种方式解释。 是否有人对此进行章节/诗歌引用?
还有另一种解决方案可以消除歧义。在每个参数周围添加一组附加括号也可以:
Bar bar( (std::istream_iterator<char>(file)), (std::istream_iterator<char>()) );
值得指出的是,这个问题与模板无关,正如我原先想的那样。