繁体   English   中英

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

[英]function vs variable declaration in C++

此代码有效:

std::ifstream f(mapFilename.c_str());
std::string s = std::string(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>());
ParseGameState(s);

因此mapFilename是一个std::stringvoid ParseGameState(const std::string&);

而这不是:

std::ifstream f(mapFilename.c_str());
std::string s(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&)

因此,在这种情况下,它似乎将s识别为函数声明而不是变量声明。

这是为什么? 这是GCC 4.2.1(Apple版本)中的错误吗? 或者GCC是否正确处理了这个问题? 这在C ++标准中是否未定义?

这是C ++的“最令人烦恼的解析”。 一个快速的Google应该会有大量的详细信息。 基本的答案是肯定的, 编译器把它当作一个函数声明-和C ++要求它这样做。 你的编译器没有任何问题(至少在这方面)。

如果它有任何安慰,那么你就会遇到很多好公司。 实际上,C ++ 0x添加了一个新的大括号初始化语法是很常见的,这在很大程度上是因为它避免了这种歧义。 使用它,你可以写如下:

std::string s{std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>()};

这将清楚地表明大括号的内容是用于初始化s值, 而不是名为s的函数的参数类型。 我不知道Apple是否有它的端口,但是gcc接受了4.5版本(或左右)的新语法。

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

因此,由于std::string有一个初始化列表构造函数,这会尝试将两个istreambuf_iterator “填充”到初始化列表中,并将其传递给带有初始化列表的std::string ctor - 但是是一个类型不匹配,所以代码无法编译。 对于(不像一些其他类型的类型std::string 没有一个初始化列表构造函数)高于转变将工作(感谢“否则......”在帖以上)。 std::string的情况下,您必须使用当前替代方法之一,例如std::string s = std:string(...)

我为错误的建议修复道歉 - 在这种情况下,更糟糕的是因为它混淆了一个可能过于混乱的问题,如果有什么需要仔细澄清,特别是在未来几年。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM