我的问题类似于this answered question,但有很大的不同。
如果我尝试编译以下内容,
void test(string x){
int x = 5;
cout << x << endl;
}
我得到了预期的警告:
In function ‘void test(std::__cxx11::string)’:
error: declaration of ‘int x’ shadows a parameter
int x = 5;
^
现在要解决我的问题;如果我的类型带有如下所示的函数调用运算符:
struct foo{
string bar;
foo(const string& bar) : bar(bar) { }
void operator()(){
cout << "my bar is \"" << bar << '"' << endl;
}
};
我可以创建一个临时对象,并使用()
或foo("this will print")();
调用其foo{"this will also print"}();
运算符
如果我尝试执行以下操作,将会收到预期的编译器错误,可以通过上面链接的帖子来解释。
void redeclaration_error(){
string x("lol");
foo(x)();
}
但是,这里的事情很奇怪:
void hmm1(string str){
foo(str)();
}
void hmm2(string str){
foo{str}();
}
虽然hmm2
在被调用时会打印出其参数,但是hmm1
绝对不会做任何事情。这是可以预期的,因为hmm1
的主体仅声明str
为foo
类型而已。但是,在hmm1
的范围内,已经从函数的参数中将str
声明为类型string
,为什么为什么不导致类似error: declaration of ‘foo str‘ shadows a parameter
的编译器错误? / p>
我了解编译器会将foo(str)();
解释为声明,并且foo(str).operator()();
和(foo(str))();
之类的行将被解释为创建临时foo对象并调用其函数调用运算符,但是为什么在这种情况下可以声明与参数同名的变量呢?
Here's and Ideone link where I was playing around with this.
答案 0 :(得分:1)
产生相同问题的更简单程序(多余的括号是红色鲱鱼):
void f(int x)
{
void x();
}
由于C ++ 17 [basic.scope.block] / 2,这是不正确的:
[...]不得在函数的最外层块中重新声明参数名称 定义,也不在与 function-try-block相关的任何处理程序的最外面的块中。
如果编译器接受此代码,则它是编译器错误。