The following appears to be a pattern employed by ZeroC ICE in the code it auto-generates, which appears to me to be a way they have made singletons (not sure why) for many releases of their tool now. Various compilers have no problem with it, until I found today that Visual Studio 2015 Update 1 (VS version 14.0.24720.00, VC++ version 19.00.23506) emits an error. Before Update 1, VS2015 also had no problem with it. I'm not sure whether it's a bug (regression?) in the VS2015 C++ compiler with Update 1, or bad (not standards-conformant) C++ code that other compilers let slide.
Here is an example of the code pattern:
class Foo {
protected:
virtual ~Foo() {}
friend class Foo_init;
};
class Foo_init {
public:
Foo init;
};
static Foo_init staticFooInit;
VS2015 Update 1 emits these errors:
example.cpp(13): error C2248: 'Foo::~Foo': cannot access protected member declared in class 'Foo'
example.cpp(3): note: see declaration of 'Foo::~Foo'
example.cpp(1): note: see declaration of 'Foo'
I found one (as yet unanswered) ZeroC ICE forum post which seems related to this, but otherwise I haven't found out in my Google searching anything that convinces me whether this is a compiler issue or bad code. I admit I don't know ZeroC ICE very well, nor do I use C++ friend classes enough to have a deep understanding of what you can and can't do with them. I'm hoping someone more knowledgeable can shed some light on it.
I am not 100% sure on your exact problem, but it reminds me of a problem I had a while ago, where forward declared classes would have an unexpected scope. this page cppreference class highlights the rules, that a forward-declared class has the most local scope. However, your example on my VS2015u3 does not fail either.
I think the fix is probably to forward declare the class which is a friend before the class, so that it has a well defined scope.
When you have a class such as
class Example {
int someFunction( class SomeOtherClass & param );
};
The compiler treats declaration of SomeOtherClass
which is within the local scope.
This means that
class Example {
int someFunction( class SomeOtherClass & param );
};
class SomeOtherClass {
...
};
Declares three classes Example
Example::SomeOtherClass
and SomeOtherClass
Changing your example to
class Foo_init;
class Foo {
protected:
virtual ~Foo() {}
friend Foo_init;
};
class Foo_init {
public:
Foo init;
};
static Foo_init staticFooInit;
Should work