8

This code used to work fine with Visual Studio 2015, but it not longer works with Visual Studio 2015 update 1.

class Foo
{
protected:

    virtual ~Foo() {};
    friend class Foo__init;
};

class Foo__init
{
public:

    Foo _init;
};

static Foo__init _Foo_init;

It fails with the following error:

Error   C2248   'Foo::~Foo': cannot access protected member declared in class 'Foo'

Is this a compiler bug or is the code ill formed?

José
  • 3,041
  • 8
  • 37
  • 58
  • Mayhbe you want to make the destructor of Foo public. – Jorge Torres Dec 23 '15 at 09:31
  • 2
    I'm not asking about that. :) – José Dec 23 '15 at 09:32
  • 2
    What happens if you put `class Foot__init;` before the definition of `Foo`? – Holt Dec 23 '15 at 09:33
  • 7
    This is an exact duplicate of http://stackoverflow.com/questions/34376316/vs2015-update-1-bug-or-bad-c-why-cant-a-friend-class-access-its-friends-pr – T.C. Dec 23 '15 at 09:34
  • 3
    Also, drop the `_Capital` and the `double__underscore`. Those names are reserved. – T.C. Dec 23 '15 at 09:36
  • 3
    @T.C. if you write an answer on either one of these questions we can mark one of them as duplicate ;) – Niels Keurentjes Dec 23 '15 at 09:43
  • @T.C. I thought double underscores were only reserved at the _start_ of names? Does this apply within names too? – underscore_d Dec 23 '15 at 10:00
  • 2
    @underscore_d That's for C, IIRC. They are reserved [everywhere](http://eel.is/c++draft/lex.name#3) in C++. – T.C. Dec 23 '15 at 10:14
  • Great concise link, thanks! Very relevant: "Each identifier that begins with an underscore is reserved to the implementation for use as a name in the global namespace." - as most people seem to overlook this and only advise against `_CapitalAfterUnderscore` - which is sure to cause undiagnosable horror when their implementation starts using `_myName` – underscore_d Dec 23 '15 at 10:22
  • @underscore_d `_myName` is only reserved in the global namespace (so the implementation can't make it a macro, for instance), unlike `_Capital`. – T.C. Dec 23 '15 at 10:28
  • @selbie it doesn't make any difference to add a Foo__init destructor – José Dec 23 '15 at 10:56
  • @Holt it's the same if I add `class Foo__init;` before the definition of `Foo` – José Dec 23 '15 at 10:57
  • @José - My bad. I removed my comment when I noticed that Foo__init doesn't actually inherit. – selbie Dec 23 '15 at 10:57
  • 1
    note that this is bad style, a destructor should either be virtual and public, or non-virtual and protected. See http://www.gotw.ca/publications/mill18.htm – TemplateRex Dec 23 '15 at 13:14

2 Answers2

3

From here:

The friend declaration appears in a class body and grants a function or another class access to private and protected members of the class where the friend declaration appears.

So it's a compiler bug. Both g++ (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010 and Ubuntu clang version 3.6.2-1 (tags/RELEASE_362/final) (based on LLVM 3.6.2) compiles this code ( I added int main() {} ).

Roman Zaitsev
  • 1,328
  • 5
  • 20
  • 28
  • 1
    It is a bug indeed, but this cannot be justified by stating that the other main vendors compile it while VC++ doesn't ;) – 101010 Dec 23 '15 at 10:13
2

It's a compiler bug. It works in VS2008

RajeshDA
  • 481
  • 2
  • 13
  • 1
    Pretty sure is a compiler bug, but destructor is required to destroy the Foo member, this should only work because the friend class. – José Dec 23 '15 at 10:59
  • Yes, In the current scenario we do not have any Foo object. it is strange why it is trying to access it. – RajeshDA Dec 23 '15 at 11:11