Why class data members can’t be initialized by direct initialization syntax?

Early proposals leading to the feature’s introduction explain that this is to avoid parsing problems.

Here’s just one of the examples presented therein:

Unfortunately, this makes initializers of the “( expression-list )” form ambiguous at the time that the declaration is being parsed:

struct S {
    int i(x); // data member with initializer
    // ...
    static int x;
};

struct T {
    int i(x); // member function declaration
    // ...
    typedef int x;
};

One possible solution is to rely on the existing rule that, if a declaration could be an object or a function, then it’s a function:

struct S {
    int i(j); // ill-formed...parsed as a member function,
              // type j looked up but not found
    // ...
    static int j;
};

A similar solution would be to apply another existing rule, currently used only in templates, that if T could be a type or something else, then it’s something else; and we can use “typename” if we really mean a type:

struct S {
    int i(x); // unabmiguously a data member
    int j(typename y); // unabmiguously a member function
};

Both of those solutions introduce subtleties that are likely to be misunderstood by many users (as evidenced by the many questions on comp.lang.c++ about why “int i();” at block scope doesn’t declare a default-initialized int).

The solution proposed in this paper is to allow only initializers of the “= initializer-clause” and “{ initializer-list }” forms. That solves the ambiguity problem in most cases. [..]

Leave a Comment