使用模板化构造函数解释为函数定义的非模板化类的实例?

时间:2011-10-23 14:49:58

标签: c++ visual-studio-2010 templates

以下代码最能证明我的问题:

#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)进行测试

2 个答案:

答案 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>()) );

值得指出的是,这个问题与模板无关,正如我原先想的那样。