30

I was wondering if there is a way such that we make all functions defined within a specific namespace friend with a class?

In particular, I have a class, for example:

class C {
    private:
        // ...
    public:
        // ...

        friend C* B::f1(C*);
        friend C* B::f2(C*);
        friend C* B::f3(C*);
        friend C* B::f4(C*);
        friend C* B::f5(C*);
};

and a namespace B as:

namespace B {
    C* f1(C* x);
    C* f2(C* x);
    C* f3(C* x);
    C* f4(C* x);
    C* f5(C* x);
};

Now, I would prefer to avoid writing 5 lines in the class definition to make all five functions of the namespace B friend with class C and just tell the compiler that all of the functions defined within the namespace B are friends with the class C (i.e. can access its private members).

A quick fix I guess is to change the namespace to a class and define the functions as its static members and then declare the class B as a friend of class C. However, out of curiosity I was wondering if such thing is possible with namespaces as well or not?

Thanks in advance.

MikeL
  • 2,369
  • 2
  • 24
  • 38

2 Answers2

28

No, it's not possible befriend a namespace. If nothing else, it would constitute a "security breach," as namespaces can be extended anywhere. So anyone could add an arbitrary function to the namespace and access the class's non-public data.

The closest you can get is the solution you propose, making those functions static members of a class and befriending the class. But then again, why not make them static members of the original class (C in your code) in the first place?

As an aside, if I ran into a need for so many friend functions in my code, it would make think again about my design, hard; I'd take it as a sign I'm doing something wrong.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • 9
    A good reason for this is for testing. Sometimes it is easier to write tests if they are able to access private members. Some people think this is bad because it violates the 'black box' testing principle, but in practice there are situations where it is better to do 'white box' testing. – Timmmm Aug 07 '17 at 09:29
  • 4
    "it would constitute a "security breach,"" - who's the attacker in this case? The developer? You're taking defensive measures against programmers, who are considered to be stupid a priori? – Tom Dec 19 '17 at 15:47
  • 3
    @Tomis Note the inverted commas. However, if you don't think private data needs protecting from modifications not intended by the class designer, why not force everything public in the first place and get rid of `private` and `protected` altogether? – Angew is no longer proud of SO Dec 20 '17 at 08:12
  • @Angew - "why not force everything public in the first place and get rid of private and protected altogether?". Actually I think that's exactly what we should do. At best use some naming conventions that indicate a member shouldn't be modified by outside classes and, hey presto, you already managed to remove 25%+ of the getter/setter boilerplate. The OOP architecture obsession simply detracts from a clean data-oriented design and just serves to make code more convoluted (and usually much slower). – Tom Dec 20 '17 at 17:59
  • 2
    @Tomis IOW, Python. But I'll take C++ compile-time safety over Python's "let's assume we all know what everyone else intends" any day. I think we should agree to disagree on this one. – Angew is no longer proud of SO Dec 21 '17 at 08:30
  • One use case I have stumbled upon is a namespace of `static const` members for a multiton template class defined beforehand. If I declare the multiton members in the multiton class itself, I have to associate each member with a template argument-qualified version of class (presumably the type of the member itself), which is unnecessarily verbose and semantically undesirable. OTOH, if the multiton members are in the separate namespace, the only way I can instantiate the multiton members using the multiton class's `private` ctor is if the namespace is be`friend`able (i.e., a class). – llf Jun 22 '18 at 22:56
  • Presuming this is a sane use case, I'd prefer to call an inextensible, be`friend`able namespace just that, instead of a class. The latter feels like a Java hack. – llf Jun 22 '18 at 22:59
6

If you promote your namespace to a class you can friend many functions at once. It comes with (many) other drawbacks, but you may actually want to have a class B (for other reasons).

class C {
    private:
        // ...
    public:
        // ...

    friend struct B_domain;
};

struct B_domain {
    static C* f1(C* x);
    static C* f2(C* x);
    static C* f3(C* x);
    static C* f4(C* x);
    static C* f5(C* x);
};
alfC
  • 14,261
  • 4
  • 67
  • 118
  • And what are these *many* drawbacks aside from being forced to write `C::`? (which could be considered a feature) – – Beyondo Aug 11 '22 at 21:49
  • @Beyondo, no ADL, which can be considered a feature. Also useless for operators. Also too verbose (if you don’t like to be verbose). – alfC Aug 12 '22 at 23:42
  • @Beyondo it is also verbose because you need static everywhere. it also needs more boiler plate as the class can be instantiated . – alfC Aug 13 '22 at 01:01