2

I've come over a little discussion today, whether it's necessary to explicitly declare friend access for an inner class/struct. Here's the (replicating sample) code in question:

struct Interface
{
    virtual void foo() = 0;
    virtual ~Interface() {}
};

class Implementation
{
    struct InterfaceImpl : Interface
    {
        InterfaceImpl(Implementation* impl)
        : impl_(impl) {}
        virtual void foo() 
        { 
            impl_->doFoo(); // << Here's what's in question!!
        } 

        Implementation* impl_;
    };

public:
    Implementation()
    : interfaceImpl_(this) {}

    Interface* getInterface() { return &interfaceImpl_; }

private:
    InterfaceImpl interfaceImpl_;

    void doFoo() {}
};

int main() {
    Implementation impl;

    return 0;
}

I've been noticing that the code compiles well, where I thought it would be necessary to have a friend struct InterfaceImpl; at the Implementationclass to get it working. So the following setups all work fine: c++11, GCC 4.8.1, GCC 4.3.2.

Is there a (pre-) standard section that confirms this is legal?

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Voted to leave closed specifically because you're **demanding** your own question be reopened. – chrylis -cautiouslyoptimistic- Feb 11 '14 at 23:07
  • @πάνταῥεῖ I'm not quite sure how this is different from the dupe... would you mind telling me? – hichris123 Feb 11 '14 at 23:08
  • I'm asking for having this question reopened, since (vs. the dupe) it consolidates all of the standard concerns (and mentions the GCC exception [which I've been tagging!!] ) nicely! It mainly differs from the given tags (relevance), and the relation for that explained exceptional behavior of GCC 4.3.2 behavior. – πάντα ῥεῖ Feb 11 '14 at 23:24
  • You can read all this as answered here (somehow) from the jungle in the proposed dupe, but by relevance of the given tags this particular Q/A might either stand on it's own, or outweigh the recommended dupe. – πάντα ῥεῖ Feb 11 '14 at 23:31

1 Answers1

8

They're not friends per se (so your interpretation is subtly wrong), but the effect you've seen is definitely standard-mandated:

[C++11: 11.7/1]: A nested class is a member and as such has the same access rights as any other member. [..]

The example given at this point in the standard is similar to yours.

However, this was not legal in C++03!

[C++03: 11.8/1]: The members of a nested class have no special access to members of an enclosing class, nor to classes or functions that have granted friendship to an enclosing class; the usual access rules (clause 11) shall be obeyed. [..]

This was considered to be a defect in the standard as early as 1998 (and made into DR #45 in 2001), which may go some way to explaining why you're seeing non-compliant behaviour in GCC, pre-C++11. In that sense, we might see the new C++11 wording as catching up with a long-standing practical reality.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • THX! That explains it! That's, what one of my other colleagues intuitively assumed, right away! **Time** to remove these unnecessary `friend` declarations everywhere ;-) (also these one's didn't hurt anything anyway )... – πάντα ῥεῖ Feb 10 '14 at 23:19
  • @πάνταῥεῖ: If it makes you feel any better, I'd have had to look it up anyway. :) – Lightness Races in Orbit Feb 10 '14 at 23:21
  • Awww!! I've been too lazy right now (**shame** on me), makes me feel worse just right now ;-) ... – πάντα ῥεῖ Feb 10 '14 at 23:23
  • **Hmmm** there's still that GCC 4.3.2 sample (which doesn't really should guarantee c++11 standards). Was this one of the ubiquitous GCC extensions then? – πάντα ῥεῖ Feb 10 '14 at 23:26
  • 3
    It might be worth mentioning that this wasn't officially the case before C++11. (I always thought it was, since that was how GCC had worked for many years, and was quite surprised to find it wasn't.) – Mike Seymour Feb 10 '14 at 23:35
  • @MikeSeymour: Hmm, okay; while true, I wouldn't feel comfortable adding that into my answer until I can adequately explain why & how GCC ignored the C++03 rule. – Lightness Races in Orbit Feb 10 '14 at 23:38
  • @MikeSeymour Good mention, since I think the given code (including the `friend` declarations) was also be supposed to be compiled with non GCC compliant c++ compilers ('embedded' crappy stuff maybe ...). As it stands, referring to [tag:c++11] standard is the only really reliable thing. – πάντα ῥεῖ Feb 10 '14 at 23:40
  • @MikeSeymour I've slightly edited my question ... – πάντα ῥεῖ Feb 10 '14 at 23:46
  • @πάνταῥεῖ: Pre C++11, there's certainly a standard section confirming that it's *not* legal. But I only have a paper copy of C++03, and that's in my office several miles away, so I can't provide the exact quote. – Mike Seymour Feb 10 '14 at 23:49
  • @MikeSeymour _'confirming that it's not legal ...'_ Good hint anyway! I'll research further ... – πάντα ῥεῖ Feb 10 '14 at 23:50
  • @LightnessRacesinOrbit **Note:** I'm asking for **definite** differences of [tag:c++03] and [tag:c++11]. – πάντα ῥεῖ Feb 10 '14 at 23:53
  • This was considered to be a defect in C++98 and was fixed long time ago [issue 45](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45) – robson3.14 Feb 10 '14 at 23:55
  • @πάνταῥεῖ: Your question now says "pre-C++11". It didn't before. :( – Lightness Races in Orbit Feb 10 '14 at 23:55
  • @LightnessRacesinOrbit Yes, sorry!! I wasn't clear enough (puzzled by the GCC 4.3.2 case). – πάντα ῥεῖ Feb 10 '14 at 23:57
  • @πάνταῥεῖ: I don't have the knowledge Mike has about that. However, I've added the relevant legalese for C++03. – Lightness Races in Orbit Feb 10 '14 at 23:58
  • 1
    @LightnessRacesinOrbit That makes it acceptable as valid answer again! (Sorry I'm that lazy, again ;) ) – πάντα ῥεῖ Feb 11 '14 at 00:00
  • @LightnessRacesinOrbit As a small side note: I'm not seeing any non-compliant behavior for GCC, but suspect there were other compilers concerned when the nested struct/class declarations were marked as `friend` explicitly. I know, some of the code in question had to deal with such stuff as using some weird compiler implementation (earlier). – πάντα ῥεῖ Feb 11 '14 at 00:24
  • @LightnessRacesinOrbit To elaborate: Kind of c++ compiler crap like [Metrowerks](http://en.wikipedia.org/wiki/Metrowerks) etc. pp. ... – πάντα ῥεῖ Feb 11 '14 at 02:00