Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Must the C++ standard library support classes that are picky about who their friends are?

This question is easiest to illustrate with an example, so here goes:

Is code like the following guaranteed to be valid, and compile & run correctly?

(Not all implementations actually compile it correctly, but I'm wondering if that's a bug.)

#include <algorithm>
class Picky
{
    friend
        Picky *std::copy<Picky const *, Picky *>(Picky const *, Picky const *, Picky *);
    Picky &operator =(Picky const &) { return *this; }
public:
    Picky() { }
};

int main()
{
    Picky const a;
    Picky b;
    std::copy<Picky const *, Picky *>(&a, &a + 1, &b);
    return 0;
}
like image 942
user541686 Avatar asked May 07 '15 20:05

user541686


1 Answers

std::copy requires an output iterator ([algorithms.general]/p5); output iterators, among other things, require *r = o to be valid ([output.iterators], Table 108) - not just "valid sometimes" or "valid in some contexts".

Since for Picky *p, a;, *p = a isn't valid in most contexts, Picky * isn't a valid output iterator.


Hmm it'd be great if you could generalize your answer to other things beyond the particular example I gave. Like, for example, std::vector::push_back(T const &), or whatever.

Befriending a member function is an absolute no-no, because you aren't even guaranteed that there's a member function with that signature ([member.functions]/p2, which Stephan T. Lavavej calls the "STL Implementers Can Be Sneaky Rule"):

An implementation may declare additional non-virtual member function signatures within a class:

  • by adding arguments with default values to a member function signature187 [Note: An implementation may not add arguments with default values to virtual, global, or non-member functions. — end note];
  • by replacing a member function signature with default values by two or more member function signatures with equivalent behavior; and
  • by adding a member function signature for a member function name.

187 Hence, the address of a member function of a class in the C++ standard library has an unspecified type.

like image 80
T.C. Avatar answered Sep 24 '22 14:09

T.C.