// Example program
#include <iostream>
#include <string>
#include <utility>
class A {
public:
int x;
};
class B {
public:
B(A &&a) : m_a(std::move(a)) {}
A m_a;
};
int main()
{
B var(std::move(A()));
// B var(A()); // does not compile why?
std::cout << var.m_a.x << "\n";
}
在上面的代码片段中,被注释掉的行无法编译。错误消息似乎将 var 视为函数声明。即使 A 具有构造函数的参数,它仍然被视为函数声明。有没有一种方法可以将它写成不被视为函数声明?在这种情况下,使用 typename 没有帮助。
最佳答案
此问题称为 the most vexing parse ,这恰好描述了您的情况,解析器不知道您是否需要函数声明或对象的实例化。从某种意义上说,它是模棱两可的,对于人类来说,一些给定的代码片段执行X,但对于编译器来说,它显然在执行Y。
绕过它的一种方法是使用 list initialization语法:
B var{A()}; // note the use of brackets
这样就没有歧义了,你想怎么调用构造函数就怎么调用。您也可以在 A
或两者中使用它:
B var(A{});
B var{A{}};
现在,为什么它是模棱两可的?以函数参数的声明为例,该函数参数是一个指向函数的指针:
int foo(int (*bar)());
这里,参数的类型是指向函数的指针,该函数不带任何参数并且返回类型为 int。声明函数指针的另一种方法是省略声明符中的括号:
int foo(int bar());
它仍然声明了一个指向与前一个相同的函数的指针。由于我们处于声明参数 ( parameter-declaration-clause ) 的上下文中,因此被解析的语法是 type-id。 , 部分建立在 abstract-declarator 之上.因此,这允许我们删除标识符:
int foo(int());
我们仍然得到相同的类型。
综上所述,让我们检查您的代码并将其与上面的示例进行比较:
B var(A());
我们有一些看起来像 B
类型的变量声明正在用 A()
初始化。到目前为止,一切都很好。但是等等,你说这不能编译!
The error message appears that it's treating var like a function declaration.
var
实际上是一个函数声明,尽管对您来说它一开始看起来并不像那样。此行为是由于 [dcl.ambig.res]/1 :
[…] the resolution is to consider any construct that could possibly be a declaration a declaration.
这句话在这里适用。回顾前面的例子:
int foo(int());
这与您的代码一样模棱两可:foo
可能是一个声明,因此解决方案是将其解释为一个声明。您的 B var(A())
也可能是一个声明,因此它具有相同的分辨率。
该标准在 [dcl.ambig.res]/1, example #1 上有这些案例的一些示例, 并且还提供了一些关于如何在 [dcl.ambig.res]/1, note #1 上消除歧义的提示。 :
[ Note: A declaration can be explicitly disambiguated by adding parentheses around the argument. The ambiguity can be avoided by use of copy-initialization or list-initialization syntax, or by use of a non-function-style cast. — end note ]
[ 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 y((int)a); // object declaration S z = int(a); // object declaration }
— end example ]
关于c++ - 有没有办法在不使用 std::move 的情况下用构造类初始化类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41295016/