函数与C ++中的变量声明 [英] function vs variable declaration in C++

查看:150
本文介绍了函数与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 :: string void 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 识别为函数声明,而不是这种情况下的变量声明。

So it seems that it recognizes s as a function declaration and not a variable declaration in this case.

为什么呢?这是一个bug在GCC 4.2.1(苹果版)?或者GCC是否正确处理?这是C ++标准中未定义的吗?

Why is that? Is this a bug in GCC 4.2.1 (Apple build)? Or does GCC handles this correctly? Is this undefined in the C++ standard?

推荐答案

这是C ++的最烦人的解析。一个快速的谷歌应该会得到很多的点击,有很多细节。基本的答案是,是的,编译器将其视为一个函数声明 - 而C ++要求它这样做。你的编译器没有问题(至少在这方面)。

This is C++'s "most vexing parse." A quick Google for that should turn up lots of hits with lots of details. The basic answer is that yes, the compiler is treating it as a function declaration -- and C++ requires that it do so. There's nothing wrong with your compiler (at least in this respect).

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

If it's any comfort, you have lots of good company in having run into this. In fact, it's sufficiently common that C++0x is added a new brace-initializer syntax, in large part because it avoids this ambiguity. Using it, you could write something like:

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

这将清楚说明大括号的内容是用于初始化 s 类型的参数添加到名为 s 的函数。我不知道苹果是否有一个端口,但gcc接受版本4.5(或更多)的新语法。

That will make it clear that the contents of the braces are intended to be values for initializing s, not types of parameters to a function named s. I don't know if Apple has a port of it yet, but gcc accepts the new syntax as of version 4.5 (or so).

编辑:Rereading N3092,Johannes是(像往常一样)相当正确。适用的语言是(§8.5.4/ 3/5):如果T有一个initializer-list构造函数,参数列表由初始化器列表作为一个参数组成;否则,参数列表由初始化器列表。

Rereading N3092, Johannes is (as usual) quite correct. The applicable language is (§8.5.4/3/5): "If T has an initializer-list constructor, the argument list consists of the initializer list as a single argument; otherwise, the argument list consists of the elements of the initializer list."

因此,由于 std :: string 有一个初始化列表构造函数,将两个 istreambuf_iterator 放入一个初始化器列表,并传递给 std :: string 初始化列表 - 但是那将是一个类型不匹配,所以代码不能编译。对于一些其他类型类型(不像 std :: string 没有有一个initializer-list ctor)上面的转换将工作(感谢否则...在上面的报价)。在 std :: string 的情况下,您必须使用当前的替代方法,如 std :: string s = std:string (...)

So, since std::string has an initializer-list constructor, this would attempt to "stuff" the two istreambuf_iterators into an initializer list, and pass that to the std::string ctor that takes an initializer list -- but that would be a type mismatch, so the code can't compile. For some other type type that (unlike std::string did not have an initializer-list ctor) the transformation above would work (thanks to the "otherwise..." in the quote above). In the case of std::string, you'd have to use one of the current alternatives such as std::string s = std:string(...).

对于不正确的建议修正,我深表歉意 - 在这种情况下,这个问题本身可能会过度混乱,如果有什么需要仔细澄清,特别是在未来几年。

I apologize for the incorrect suggested fix -- in this case, one that's all the worse because it confuses an issue that will probably be excessively confusing on its own, and if anything will need careful clarification, especially over the next few years.

这篇关于函数与C ++中的变量声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆