为成员对象内联使用非默认显式构造函数

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 的原始提案解决了这个问题:

N2756

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)
{
}