bug or feature

I've wrote some code which failed to compile by gcc-4.4.1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//here was mistake - struct written instead of class
class Access
{
  friend class Test;
  struct Tag 
    {};
};

template <typename AccessTag>
struct Foo
{};

class Test
  :public Foo<Access::Tag> // error: Access::Tag is private within this context
{
  Foo<Access::Tag> tag; // compiled ok
};


Can't figure out is this really error, or just a bug in compiler.
Last edited on
It compiles fine with g++ 4.4.3 and 4.5.0
The above compiles cleanly for me under gcc 3.3.3, gcc 4.1.2 and clang.
Bazzy, jsmith
sorry, i've made a mistake in a sample - fixed
Ok, now gcc 3.3.3 and 4.1.2 both winge, but clang still compiles cleanly. I'd trust clang more than gcc,
and the code looks right to me, so I'd say it is a problem with gcc.
Interesting, comeau also winges for the same reason as gcc.

http://www.comeaucomputing.com/tryitout/

Here's the simplest version of the code I can come up with that still does not compile:

1
2
3
4
5
6
7
8
9
class Access
{
  friend struct Test;
  struct Tag {};
};

struct Test : Access::Tag
{
};


It seems that the friendship is not occurring until the open brace on struct Test.
@jsmith

"It seems that the friendship is not occurring until the open brace on struct Test."
Yes, and i can't still understand what the standard says about such cases.. Code looks right to me too.
Unlike structs all class members are private if not specified another access level. ;-)

1
2
3
4
5
class Access
{
  friend struct Test;
  struct Tag {};
};
is similar
1
2
3
4
5
6
class Access
{
  friend struct Test;
private:
  struct Tag {};
};

You must write:
1
2
3
4
5
6
class Access
{
  friend struct Test;
public:
  struct Tag {};
};
or unnatural style:
1
2
3
4
5
struct Access
{
  friend struct Test;
  struct Tag {};
};


EDIT: i mean that it is not a bug =)
Last edited on
boolivar: By declaring Test to be a friend of Access (line 3 of your first code block above), Test
should have access to Access' private elements. That is what friendship does.

For comparison, take my "simplest example" code above, remove the ": Access::tag" from line 7,
and add between lines 8 and 9 a member variable of type Access::Tag. eg:

1
2
3
4
5
6
7
8
9
10
class Access
{
  friend struct Test;
  struct Tag {};
};

struct Test
{
   Access::Tag t;
};


And note that this compiles cleanly.
This compiles cleanly:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Access
{
  friend class Test;

private:
  class Tag {};
};

class Test
{
public:
  class T : Access::Tag {};
};


That is what friendship does.
@boolivar
look at comment at string 16 in original example - the question was not about friendship and access inside the class braces.

However, i found the answer in 11.4.2 of the standard, quote:

Also, because the base-clause of the friend class is not part of its member declarations, the base-clause of the friend class cannot access the names of the private and protected members from the class granting friendship.

end qoute

So this is not a bug, alas.
Last edited on
But the good news that in C++0x (according to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3126.pdf) the corresponding rule is

Declaring a class to be a friend implies that the names of private and protected members from the class
granting friendship can be accessed in the base-speciļ¬ers and member declarations of the befriended class.

end quote
Thank you for the enlightenment.

I guess every compiler we tried was right then, since there is no wrong answer. It's just
a matter of what version of the standard your compiler claims to support :)

Topic archived. No new replies allowed.