R_Kapp
R_Kapp

Reputation: 2858

Default argument allowing constructor to call private method

I have the class

class A
{
public:
    class Key
    {
        Key() {}
        Key(Key const &) {}
    };

    A(Key key, int a = 5) {}
};

The constructor for Key is private, so no one should be able to construct an object A. However, with the following code:

int main() {
    A a(A::Key()); // this compiles !!!
    A a2(A::Key(), 5); // this doesn't
    // somehow defaulting the argument causes the private constructor
    // to be OK - no idea why
    return 0;
}

By making use of the default argument for int a in my constructor, the compiler happily compiles my usage of A::Key() despite the fact that it is private. If I explicitly give a value for a, though, the compiler correctly recognizes that I am trying to use a private constructor and errors out. Why is this? Is there someway to force the compiler to error out for the first example as well?

See here for live example.

Upvotes: 6

Views: 124

Answers (1)

NathanOliver
NathanOliver

Reputation: 180500

This is because of the most vexing parse.

A a(A::Key());

Does not create a A named a and construct it with a temporary A::Key. It creates a function a that returns an A and takes an unnamed pointer to function that returns a A::Key.

If you add a pair of parentheses to it you will get a compiler error

A a((A::Key()));

That you are trying to call a private constructor. Alternatively you can use uniformed initialization which also disambiguate it and will cause a compile error

A a(A::Key{});

Upvotes: 7

Related Questions