Reputation: 54939
In C++11 (or future), is there some simple variation of the following which is legal?
class A
{
public:
std::vector<char> b(123); // declare a vector with 123 elements
};
The closest I can find is a bit clunky, and maybe inefficient...
class A
{
public:
std::vector<char> b = std::vector<char>(123);
};
I'm trying to avoid using an initializer list. I prefer to consolidate the declaration and initialization of b
into a single line of code. The vector will always be the same size.
I'm using std::vector
in this example, but presumably the answer would be more generally applicable.
For good measure, here's the error message from gcc
version 4.8:
error: expected identifier before numeric constant std::vector b(123);
and here's the message from clang
version 3.7:
error: expected parameter declarator std::vector b(123);
Upvotes: 2
Views: 211
Reputation: 76
Highly unlikely. The original proposal to allow NSDMIs in the first place addresses this issue:
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.
There is nothing inefficient about the clunky way of initialization unless your compiler doesn't employ copy elision (and all major ones do). The issue is that the language designers of C++ have backed themselves into a corner. Because initializer list constructors are greedy, brace initialization will construct a vector with the given elements, while the older syntax using parentheses calls the explicit constructor to set a size.
Except you can't use that constructor in a NSDMI. Unless you use an equals sign.
If for some reason that bothers you, there are some clunky workarounds:
std::vector<char> c = decltype(c)(123);
// ...
using VChar = std::vector<char>;
VChar v = VChar(123);
Or realize that new features do not preclude existing features:
std::vector<char> c;
A() : c(123)
{
}
Upvotes: 6