Re: Class templates and friend function templates

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance





John Carson wrote:
[...]
> VC++, on the other hand, is doing at least two things wrong:

Our (EDG) compiler has a "Microsoft bugs" mode that also
emulates this. I looked it up in our documentation...

> 1. It is instantiating an instance of the operator from
>
> template <class U, class V>
> bool operator == (C<U>& u, C<V> &v)
> {
> cout << c0.x;
> return u.x == v.x;
> }
>
> when it should instead be producing a link error for the more specialised
> form of the operator declared in the friend declaration.
>
> 2. It is granting this operator friendship rights that it shouldn't have.

While this is true, they are both the consequence of the same bug:
Microsoft compilers seem to treat friend function declarations as
what used to be known as "guiding function declarations". (I meant
to write about those in the "C++ Templates" book, but it somehow
never made it into the text.) A "guiding function declaration" was a
declaration of an instance of a template. It was different from an
explicit specialization in that it did not inhibit the instance from
being generated. (The ARM hints at the existence of guiding
functions and for a while they were formally specified in the
Working Paper that eventually became the C++ standard. They were
removed from the standard when the notion of "signature" was
finalized, if I remember correctly.)

So what's happening in the example is that the friend declaration
injected by MSVC++ is _not_ equivalent to

template<typename Other>
bool operator==(C<int>&, C<Other>&);

but to some other construct that can no longer be expressed in
standard C++ (and in fact, I don't think the parameterized form
was ever possible). For argument's sake:

__guide template<typename Other>
bool operator==(C<int>&, C<Other>&);

This "guiding declaration" gets matched to a template declaration
that _follows_ it (a rather funny concept for C++, IMO). The final
result is that a subset of instances is made a friend of the class,
which is in fact what the original poster wanted. You can verify
this by replacing "C<Other>" in the friend declaration by "C<Other*>":
I think that will result in access errors.

(Note that this analysis is based on observation alone. The MSVC++
compiler may very well work completely differently internally.)

As you can imagine, figuring out that kind of stuff and emulating
the associated bugs in an otherwise standard compiler is loads of
fun ;-)

Daveed

.



Relevant Pages

  • Re: friend class in template
    ... This template takes 3 type parameters, the first of which is named ... The friend declaration attempts to declare the class ... the friend declaration doesn't do what the author apparently ... thought it would do (at least not on a conforming compiler). ...
    (microsoft.public.vc.language)
  • What is a "bug", and what is "good code"? (or: more default_nettype)
    ... module adder2 (output wire sum, co, ... to summarise, "Declarations Can Add Bugs", "a flawed declaration ... If the compiler catches a problem, then that's simply a syntax error ... not set to none, are actually real bugs, in that they get ...
    (comp.lang.verilog)
  • Problem with Friend
    ... that is a friend of that class the compiler is complaining ... : see declaration of 'database_id' ...
    (alt.comp.lang.learn.c-cpp)
  • Re: Question about 6.2.4 of C99
    ... compilers to reuse memory in some cases, ... muddying up the semantics and/or making the programmer work harder. ... than it would be if the declaration created and really ... I understand why the VLA rules are the way they are. ...
    (comp.std.c)
  • Re: Question about 6.2.4 of C99
    ... compilers to reuse memory in some cases, ... muddying up the semantics and/or making the programmer work harder. ... the same way it does for VLAs? ... I write an intra-block declaration and every time I read one I ...
    (comp.std.c)