C++ C+中的函数与变量声明+;

C++ C+中的函数与变量声明+;,c++,variables,function,declaration,C++,Variables,Function,Declaration,此代码适用于: std::ifstream f(mapFilename.c_str()); std::string s = std::string(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>()); ParseGameState(s); 这就是错误: game.cpp: In member function ‘int Game::LoadMapFromFile(const std::

此代码适用于:

std::ifstream f(mapFilename.c_str());
std::string s = std::string(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>());
ParseGameState(s);
这就是错误:

game.cpp: In member function ‘int Game::LoadMapFromFile(const std::string&)’:
game.cpp:423: error: no matching function for call to ‘ParseGameState(std::string (&)(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> > (*)()))’
game.cpp:363: note: candidates are: ParseGameState(const std::string&)
game.cpp:在成员函数“int game::LoadMapFromFile(const std::string&)”中:
game.cpp:423:错误:调用“ParseGameState(std::string(&)(std::istreambuf_迭代器,std::istreambuf_迭代器(*))”时没有匹配的函数
game.cpp:363:注意:候选项是:ParseGameState(const std::string&)
因此,在本例中,它似乎将
s
识别为函数声明,而不是变量声明

为什么呢?这是GCC4.2.1(苹果版)中的一个bug吗?或者GCC是否正确地处理了这个问题?这是C++标准中未定义的吗?< /p> < p>这是C++的“最令人讨厌的解析”。一个快速的谷歌应该会带来很多细节。基本的答案是,是的,编译器将它视为函数声明——而C++要求它这样做。您的编译器没有问题(至少在这方面)

如果有什么安慰的话,你有很多很好的同伴。事实上,C++0x添加新的大括号初始值设定项语法非常常见,这在很大程度上是因为它避免了这种歧义。使用它,您可以编写如下内容:

std::string s{std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>()};
std::string s{std::istreambuf_迭代器(f),std::istreambuf_迭代器();
这将清楚地表明,大括号的内容是用于初始化
s
的值,而不是名为
s
的函数的参数类型。我不知道苹果是否有它的一个端口,但是gcc从版本4.5开始接受新的语法

编辑:重读N3092,约翰内斯(像往常一样)非常正确。适用语言为(§8.5.4/3/5):“如果T具有初始值设定项列表构造函数,则参数列表由初始值设定项列表作为单个参数组成;否则,参数列表由初始值设定项列表的元素组成。”

因此,由于
std::string
有一个初始值设定项列表构造函数,这将尝试将两个
istreambuf_迭代器
s“填充”到初始值设定项列表中,并将其传递给接受初始值设定项列表的
std::string
ctor,但这将是一种类型不匹配,因此代码无法编译。对于某些其他类型(不像
std::string
没有初始值设定项列表),上面的转换可以工作(多亏了上面引号中的“否则…”)。在
std::string
的情况下,您必须使用当前的备选方案之一,例如
std::string s=std:string(…)


我为不正确的建议修复表示歉意——在这种情况下,更糟糕的是,它混淆了一个问题,而这个问题本身可能会过于混乱,如果有任何问题需要仔细澄清,尤其是在未来几年内。

谢谢!对于最麻烦的解析也是一个很好的解释。看起来上面的
std::string
变量声明在C++0x中不起作用:因为
std::string
有一个初始值设定项列表构造函数,整个
{…}
将作为一个参数,并且将尝试初始化
初始值设定项\u list
参数,但编译失败:(@Johannes:是的,我想你是对的。我几乎想知道,如果这是重写的,而不是考虑列表初始值设定项,然后(只有在不存在的情况下)是否会更好考虑其他的Cor,如果它只是建立了一个超载集并选择了一个最佳匹配——可能是通过创建一个初始化器列表的微小调整,相当于没有关于匹配性的转换(附带条件是我只考虑了几分钟),因此可能会引起一个微妙的(甚至是耀眼的)。我错过的问题)。似乎已经解决了:@Johannes:啊,是的。看来我参加那个聚会有点晚了…:-)
std::string s{std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>()};