为成员对象内联使用非默认显式构造函数
Inline use of non-default explicit constructor for a member object
在 C++11(或未来)中,是否存在以下合法的一些简单变体?
class A
{
public:
std::vector<char> b(123); // declare a vector with 123 elements
};
我能找到的最接近的有点笨拙,而且效率可能很低...
class A
{
public:
std::vector<char> b = std::vector<char>(123);
};
我试图避免使用初始化列表。我更喜欢将 b
的声明和初始化合并到一行代码中。矢量将始终具有相同的大小。
我在这个例子中使用了 std::vector
,但大概答案会更普遍适用。
以下是 gcc
4.8 版的错误消息:
error: expected identifier before numeric constant
std::vector b(123);
这是来自 clang
版本 3.7 的消息:
error: expected parameter declarator
std::vector b(123);
极不可能。首先允许 NSDMI 的原始提案解决了这个问题:
An issue raised in Kona regarding scope of identifiers:
During discussion in the Core Working Group at the September ’07
meeting in Kona, a question arose about the scope of identifiers in
the initializer. Do we want to allow class scope with the possibility
of forward lookup; or do we want to require that the initializers be
well-defined at the point that they’re parsed?
What’s desired:
The motivation for class-scope lookup is that we’d like to be able to
put anything in a non-static data member’s initializer that we could
put in a mem-initializer without significantly changing the semantics
(modulo direct initialization vs. copy initialization):
int x();
struct S {
int i;
S() : i(x()) {} // currently well-formed, uses S::x()
// ...
static int x();
};
struct T {
int i = x(); // should use T::x(), ::x() would be a surprise
// ...
static int x();
};
Problem 1:
Unfortunately, this makes initializers of the “( expression-list )”
form ambiguous at the time that the declaration is being parsed:
...
The proposal:
CWG had a 6-to-3 straw poll in Kona in favor of class-scope lookup;
and that is what this paper proposes, with initializers for non-static
data members limited to the “= initializer-clause” and “{
initializer-list }” forms. We believe:
Problem 1: This problem does not occur as we don’t propose the ()
notation. The = and {} initializer notations do not suffer from this
problem.
除非您的编译器不使用复制省略(而且所有主要编译器都使用),否则这种笨拙的初始化方式并没有什么低效的。问题是 C++ 的语言设计者已经把自己逼到了墙角。因为初始化列表构造函数是 greedy,大括号初始化将使用给定的 elements 构造一个向量,而使用括号的旧语法调用显式构造函数来设置一个尺码。
除非您不能在 NSDMI 中使用该构造函数。除非你使用等号。
如果出于某种原因困扰您,可以使用一些笨拙的解决方法:
std::vector<char> c = decltype(c)(123);
// ...
using VChar = std::vector<char>;
VChar v = VChar(123);
或者意识到新功能并不排除现有功能:
std::vector<char> c;
A() : c(123)
{
}
在 C++11(或未来)中,是否存在以下合法的一些简单变体?
class A
{
public:
std::vector<char> b(123); // declare a vector with 123 elements
};
我能找到的最接近的有点笨拙,而且效率可能很低...
class A
{
public:
std::vector<char> b = std::vector<char>(123);
};
我试图避免使用初始化列表。我更喜欢将 b
的声明和初始化合并到一行代码中。矢量将始终具有相同的大小。
我在这个例子中使用了 std::vector
,但大概答案会更普遍适用。
以下是 gcc
4.8 版的错误消息:
error: expected identifier before numeric constant std::vector b(123);
这是来自 clang
版本 3.7 的消息:
error: expected parameter declarator std::vector b(123);
极不可能。首先允许 NSDMI 的原始提案解决了这个问题:
An issue raised in Kona regarding scope of identifiers:
During discussion in the Core Working Group at the September ’07 meeting in Kona, a question arose about the scope of identifiers in the initializer. Do we want to allow class scope with the possibility of forward lookup; or do we want to require that the initializers be well-defined at the point that they’re parsed?
What’s desired:
The motivation for class-scope lookup is that we’d like to be able to put anything in a non-static data member’s initializer that we could put in a mem-initializer without significantly changing the semantics (modulo direct initialization vs. copy initialization):
int x(); struct S { int i; S() : i(x()) {} // currently well-formed, uses S::x() // ... static int x(); }; struct T { int i = x(); // should use T::x(), ::x() would be a surprise // ... static int x(); };
Problem 1:
Unfortunately, this makes initializers of the “( expression-list )” form ambiguous at the time that the declaration is being parsed:
...
The proposal:
CWG had a 6-to-3 straw poll in Kona in favor of class-scope lookup; and that is what this paper proposes, with initializers for non-static data members limited to the “= initializer-clause” and “{ initializer-list }” forms. We believe:
Problem 1: This problem does not occur as we don’t propose the () notation. The = and {} initializer notations do not suffer from this problem.
除非您的编译器不使用复制省略(而且所有主要编译器都使用),否则这种笨拙的初始化方式并没有什么低效的。问题是 C++ 的语言设计者已经把自己逼到了墙角。因为初始化列表构造函数是 greedy,大括号初始化将使用给定的 elements 构造一个向量,而使用括号的旧语法调用显式构造函数来设置一个尺码。
除非您不能在 NSDMI 中使用该构造函数。除非你使用等号。
如果出于某种原因困扰您,可以使用一些笨拙的解决方法:
std::vector<char> c = decltype(c)(123);
// ...
using VChar = std::vector<char>;
VChar v = VChar(123);
或者意识到新功能并不排除现有功能:
std::vector<char> c;
A() : c(123)
{
}