21

The following C++11 code compiles successfully on my GCC 4.8:

struct NonStack
{
private:
  NonStack() = default;
public:
  static NonStack* Create(){
    return new NonStack;
  }
};
NonStack a;

int main() { }

However the following gives a compilation error:

struct NonStack
{
private:
  NonStack(){}
};

NonStack a; 

int main() { }

Why does the first one succeed? Shouldn't the private defaulted constructor prohibit creation of an object via NonStack a;?

Praetorian
  • 106,671
  • 19
  • 240
  • 328
thomas
  • 505
  • 3
  • 12

1 Answers1

18

This is gcc bug 54812, the compiler fails to respect access specifiers for explicitly defaulted special member functions. Bug 56429, which is marked as a duplicate of the earlier one, has a test case that is almost identical to the example in the question.

The solutions are to upgrade to gcc4.9, which resolves the issue. Or create an empty body for the constructor, instead of explicitly defaulting it, as you've done in the second example.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • 3
    Note: that bug links to [core language issue 1507](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1507). It wasn't a bug in GCC. The standard really did use to say that since the constructor was trivial, the constructor wasn't called, and if the constructor isn't called, the fact that it's `private` isn't a problem. –  Sep 08 '14 at 10:01
  • @hvd Agreed that the private trivial constructor being inaccessible but well-formed was a defect in the standard, but the gcc bug report still indicates a bug because they're applying that logic to inaccessible trivial destructors. The answer could be worded better though, and I'll update it in a little while. – Praetorian Sep 08 '14 at 16:26
  • Ah right, I missed that, the standard has had appropriate wording for that for longer. Perhaps of interest, the standard still doesn't seem to have a prohibition against `delete`ing a pointer to an incomplete class type which would have an inaccessible trivial destructor, it's only undefined behaviour if the destructor is actually non-trivial. –  Sep 08 '14 at 17:32
  • @hvd Finally found the time to update this, but now I'm not sure I agree that this is an effect of issue 1507. That deals with value initialization specifically, but the example in the question is default initialization. [dcl.init]/6 in N3337 clearly states that default initialization is ill-formed if the default constructor is inaccessible. – Praetorian Sep 10 '14 at 05:07