Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 739
R_Kapp Avatar asked Sep 29 '17 14:09

R_Kapp


1 Answers

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{});
like image 97
NathanOliver Avatar answered Nov 09 '22 21:11

NathanOliver