template private inheritance in vc++10 is not accessible
Asked Answered
Q

2

7

The following code compiles using GCC 4.4.6 and Comeau 4.3.10.

#include <iostream>

struct A { int name; };
template<typename T> struct C : T { using T::name; };
struct B : private A { friend struct C<B>; };

int main()
{
    C<B> o;
    o.name = 0;
}

It gives the following error in VC++10:

main.cpp(4): error C2877: 'A::name' is not accessible from  'A'
main.cpp(10): error C2247: 'A::name' not accessible because 'B' uses 'private' to inherit from 'A'

What's a good cross-compiler workaround that allows o.name = 0;?

Note: Adding using A::name to B takes care of the problem, but publishes the A::name member to everyone, whereas it should only be visible to a particular template instantiation, namely C<B>.

Quelpart answered 6/9, 2012 at 6:49 Comment(16)
Shouldn't that be using T::name; ? How is this language feature called ?Kelula
Access declarations, see #2085301Quelpart
Please note that the answer to that question states that not using the "using" keyword is deprecated. I know it doesn't solve your problem, but still ;)Kelula
By the way, stating the version of VC++ may help.Kelula
Ok, I'll just add the using keyword, this should kill the red herring.Quelpart
Added the compiler versions, npQuelpart
What happens if you add using A::name; into B?Outrage
Also you can try template <typename T> friend struct C<T>;. It's a bit different, but maybe it works?Outrage
@Kerrek SB, while I only want one particular template instantiation to be a friend, I tried your suggestion to no avail.Quelpart
@Nick: OK, it was just a guess. Your compiler doesn't seem to be standards-compliant, I suppose.Outrage
@Kerrek SB, I updated the question regarding using A::name w/in B.Quelpart
It is definitely not compliant. How do I go about keeping this cross-compiler compatible, ideally w/o writing compiler specific defines?Quelpart
@Nick: Adding using A::name does not have any downsides. It shouldn't be necessary according to the standard, but it definitely has no ill effects. Name lookup comes way before access control. But it also doesn't hurt and doesn't get in the way, so feel free to leave it in.Outrage
does friend struct C<B> actually do anything in your example? C inherits from B anyway, and B doesn't have any members of its own. Might be it's just me missing some part of C++ knowledge, though ;).Mucoprotein
Actually, you could argue that B does has a member, namely the privately inherited A instance.Quelpart
ah, missed that point, name becoming a private member of B through private inheritance, and therefore accessible for friends, but inaccessible derived classesMucoprotein
D
5

Work around is what @kerrekSB suggested, add using A::name; in class B:

struct A { int name; };
template<typename T> struct C : T { using T::name; };

struct B : private A { 
using A::name; 
friend struct C<B>;
};

your initial example didn't work cause class A is private to B and class C<B> is friend of B but when you access member name from object of C<B> , line using T::name; creates problem since the class B doesn't has any member name in it. it's scope search which find the member name when you try to access it via object of class B

Edit :

Adding using A::name to B takes care of the problem, but publishes the A::name member to everyone, whereas it should only be visible to a particular template instantiation, namely C

if that's the case , then simply declare statement using A::name; in private section in class B i.e

struct B : private A {
protected: using A::name; 
public:
friend struct C<B>;
};
Developing answered 6/9, 2012 at 7:59 Comment(3)
the funny thing is when you try a simplified example without templates (e.g. a class C, deriving from B, which derives privately from A with member name, then both gcc and VC++ complain about using B::name in C - of course, because name is not member of B... but why gcc doesn't complain in OP's example is a riddle to me, VC++'s behaviour is correct in my eyes.Mucoprotein
@nyarlathotep gcc has bug in this I'd say though above example works in gccDeveloping
Why not use protected: using A::name;? That would solve my problems completely and keep the intended isolation level.Quelpart
M
2

There seems to be a fundamental difference in visibility considerations between gcc and VC++ when using member using-declarations; check this simplified example without templates:

struct A { int name; };
struct B: private A { friend struct C; };
struct C: B {using B::name; };

int main()
{
   C o;
   o.name = 0;
}

It will compile on gcc but not on VC++ (with basically the same error as in the question). Will have to consult the standard on who is doing it right...

Mucoprotein answered 6/9, 2012 at 8:10 Comment(4)
Did you take the friend struct C<B> line into account?Quelpart
@Nick: Does that line change anything? I don't think it does; see my comment on the question. C will still be friend to B (which doesn't have any members), not to A (which it would need in order to get access to A::name). But feel free to convince me otherwise ;)Mucoprotein
That line enables GCC to compile.Quelpart
Ah yes, VC++ probably has stricter name resolution rules when it comes to using, since my simplified example above also won't compile in VC++, while it does in gcc.Mucoprotein

© 2022 - 2024 — McMap. All rights reserved.