C++ 关于最令人烦恼的解析的令人困惑的细节
我的问题是如何将以下行解析为函数声明:C++ 关于最令人烦恼的解析的令人困惑的细节,c++,most-vexing-parse,C++,Most Vexing Parse,我的问题是如何将以下行解析为函数声明: vector<int> v(istream_iterator<int>(cin), istream_iterator<int>()); 向量v(istream_迭代器(cin),istream_迭代器()); 我了解最麻烦的解析的大部分细节,以及为什么第二个临时迭代器可以解释为一个类型,即返回迭代器且不带参数的函数,但我不明白为什么第一个临时迭代器可以解释为一个类型。它代表什么类型?我的想法是,它可能是某种函数类型,
vector<int> v(istream_iterator<int>(cin), istream_iterator<int>());
向量v(istream_迭代器(cin),istream_迭代器());
我了解最麻烦的解析的大部分细节,以及为什么第二个临时迭代器可以解释为一个类型,即返回迭代器且不带参数的函数,但我不明白为什么第一个临时迭代器可以解释为一个类型。它代表什么类型?我的想法是,它可能是某种函数类型,但我看不出名称
cin
是如何使用的。是否声明该参数是名为cin
的istream\u迭代器?如果是,这是否意味着您可以任意将参数的名称插入函数中?如果是,原因是什么?是的,它是参数名。是的,你可以加上一组括号,因为有时候你不得不这样做
如果参数是函数指针,void(*f)(
您需要这样编写它
编写标准的人没有花宝贵的时间精确指出括号是允许的或实际需要的情况,因此标准只是说可以使用括号。是的,这是参数名称。是的,你可以加上一组括号,因为有时候你不得不这样做
如果参数是函数指针,void(*f)(
您需要这样编写它
编写标准的人没有花宝贵的时间确切地指出括号是允许的或实际需要的情况,因此标准只是说你可以使用括号。istream\u iterator(cin)
与istream\u iterator cin
完全相同,但有多余的参数。这个声明符语法是从C继承而来的,我认为即使是C的发明者(Ken Thompson?)也将其描述为一个错误。istream\u迭代器(cin)
与istream\u迭代器cin
完全相同,但有多余的参数。这个声明符语法是从C继承而来的,我想即使是C的发明者(Ken Thompson?)也将其描述为一个错误。我是否已经说过我非常喜欢Clang
只需尝试以下(简化代码)
#包括
void-foo(std::vector);
int main(){
向量v(int(i),int());
傅(五),;
}
在新更名的游戏中(好吧,它只是从llvm gcc变成了clang)
你会得到:
/tmp/webcompile/_21483_0.cc:6:21: warning: parentheses were disambiguated
as a function declarator
std::vector<int> v(int(i), int());
^~~~~~~~~~~~~~~
/tmp/webcompile/_21483_0.cc:7:3: error: no matching function for call to 'foo'
foo(v);
^~~
/tmp/webcompile/_21483_0.cc:3:6: note: candidate function not viable:
no known conversion from 'std::vector<int> (int, int (*)())'
to 'std::vector<int>' for 1st argument
void foo(std::vector<int>);
^
3 diagnostics generated.
/tmp/webcompile/_21483_0.cc:6:21:警告:括号已消除歧义
作为函数声明器
向量v(int(i),int());
^~~~~~~~~~~~~~~
/tmp/webcompile/_21483_0.cc:7:3:错误:调用“foo”时没有匹配的函数
傅(五),;
^~~
/tmp/webcompile/_21483_0.cc:3:6:注意:候选函数不可行:
没有从“std::vector(int,int(*)())”的已知转换
到第一个参数的“std::vector”
void-foo(std::vector);
^
生成3个诊断。
因此,@john是对的,int(i)
被解释为int i
,即函数的命名参数。我是否已经说过我非常喜欢Clang
只需尝试以下(简化代码)
#包括
void-foo(std::vector);
int main(){
向量v(int(i),int());
傅(五),;
}
在新更名的游戏中(好吧,它只是从llvm gcc变成了clang)
你会得到:
/tmp/webcompile/_21483_0.cc:6:21: warning: parentheses were disambiguated
as a function declarator
std::vector<int> v(int(i), int());
^~~~~~~~~~~~~~~
/tmp/webcompile/_21483_0.cc:7:3: error: no matching function for call to 'foo'
foo(v);
^~~
/tmp/webcompile/_21483_0.cc:3:6: note: candidate function not viable:
no known conversion from 'std::vector<int> (int, int (*)())'
to 'std::vector<int>' for 1st argument
void foo(std::vector<int>);
^
3 diagnostics generated.
/tmp/webcompile/_21483_0.cc:6:21:警告:括号已消除歧义
作为函数声明器
向量v(int(i),int());
^~~~~~~~~~~~~~~
/tmp/webcompile/_21483_0.cc:7:3:错误:调用“foo”时没有匹配的函数
傅(五),;
^~~
/tmp/webcompile/_21483_0.cc:3:6:注意:候选函数不可行:
没有从“std::vector(int,int(*)())”的已知转换
到第一个参数的“std::vector”
void-foo(std::vector);
^
生成3个诊断。
因此,@john是对的,int(i)
被解释为int i
,即函数的命名参数。在标准(2003)中有一个章节称为歧义解决
,专门讨论此类语法。我想如果你自己读这一节,我不需要进一步解释,因为它有很多例子,非常清楚
那么,给你:
8.2歧义解决方案[dcl.ambig.res]
1-函数样式转换和6.8中提到的声明之间的相似性引起的歧义也可能发生在声明的上下文中在该上下文中,可以选择在参数名周围有一组冗余括号的函数声明和将函数样式转换为初始值设定项的对象声明之间进行选择。正如在6.8中提到的歧义一样,该解决方案是考虑任何可能是声明的结构。
2-函数样式转换和类型id之间的相似性引起的歧义可能会在不同的上下文中出现。模糊性表现为在函数样式转换表达式和类型声明之间的选择解决方案是,在其语法上下文中可能是类型id的任何构造都应被视为类型id。
标准(2003)中有一个章节称为歧义解决
,专门针对此类语法。我想如果你自己读这一节,我不需要进一步解释,因为它有很多例子,非常清楚
那么,给你:
8.2歧义解决方案[dcl.ambig.res]
1-由于第
[Example:
struct S {
S(int);
};
void foo(double a)
{
S w(int(a)); // function declaration
S x(int()); // function declaration
S y((int)a); // object declaration
S z = int(a); // object declaration
}
—end example]
3- [Example:
#include <cstddef>
char *p;
void *operator new(size_t, int);
void foo() {
const int x = 63;
new (int(*p)) int; // new-placement expression
new (int(*[x])); // new type-id
}
//4 - For another example,
template <class T>
struct S {
T *p;
};
S<int()> x; // type-id
S<int(1)> y; // expression (ill-formed)
//5 - For another example,
void foo()
{
sizeof(int(1)); // expression
sizeof(int()); // type-id (ill-formed)
}
//6 - For another example,
void foo()
{
(int(1)); //expression
(int())1; //type-id (ill-formed)
}
—end example]
[Example:
class C { };
void f(int(C)) { } // void f(int (*fp)(C c)) { }
// not: void f(int C);
int g(C);
void foo() {
f(1); //error: cannot convert 1 to function pointer
f(g); //OK
}
//For another example,
class C { };
void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));
// not: void h(int *C[10]);
—end example]