Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 关于最令人烦恼的解析的令人困惑的细节_C++_Most Vexing Parse - Fatal编程技术网

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)(
您需要这样编写它


编写标准的人没有花宝贵的时间确切地指出括号是允许的或实际需要的情况,因此标准只是说你可以使用括号。

istream\u iterator(cin)
istream\u iterator 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
,即函数的命名参数。

在标准(2003)中有一个章节称为
歧义解决
,专门讨论此类语法。我想如果你自己读这一节,我不需要进一步解释,因为它有很多例子,非常清楚

那么,给你:

8.2歧义解决方案[dcl.ambig.res]

1-函数样式转换和6.8中提到的声明之间的相似性引起的歧义也可能发生在声明的上下文中在该上下文中,可以选择在参数名周围有一组冗余括号的函数声明和将函数样式转换为初始值设定项的对象声明之间进行选择。正如在6.8中提到的歧义一样,该解决方案是考虑任何可能是声明的结构。 2-函数样式转换和类型id之间的相似性引起的歧义可能会在不同的上下文中出现。模糊性表现为在函数样式转换表达式和类型声明之间的选择解决方案是,在其语法上下文中可能是类型id的任何构造都应被视为类型id。


你能举一个例子说明这在哪里是必要的吗?int*a[10]是一个由10个int指针组成的数组,但是int(*a)[10]是一个指向一个由10个整数组成的数组的指针(我希望我得到的是正确的方法)。啊,与其说是“你需要它”,不如说是“某些类型需要它”。我将您的评论误解为“有些类型的编译时错误是因为没有包含一组额外的括号,否则就没有必要了。”它是函数的一个参数。我认为它们是在所问问题的上下文中出现的(也许我不应该确切地说)。需要详细说明吗?@Nawaz:
istream\u迭代器(cin)
不是被解释为一个表达式,而是一个参数声明,这就是问题的关键所在。@Nawaz,你误解了。我没有说是istream迭代器(cin)
导致了这个问题。OP特别询问如何将
istream\u迭代器(cin)
解释为参数声明。这就是我回答的问题。@Nawaz,不需要上下文。它始终是
cin
的声明,不能是临时对象。
/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.
[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]