[cfe-dev] Visibility of inline defined friend template function

Richard Smith richard at metafoo.co.uk
Tue Aug 27 15:49:15 PDT 2013


On Sun, Aug 25, 2013 at 11:23 AM, Will Wilson <will at indefiant.com> wrote:

> Apologies, for the delay - this had to go on the backburner for a while.
> Here are my results with MSVC 10...
>
> *Test 1: Original*
>
> class S {
> public:
>    friend void f() {}
>   template<typename T> friend void g(T&) {}
> };
> void h() {
>   f(); // error C3767: 'f': candidate function(s) not accessible \
>        // could be the friend function at
> 'friend_functions_inline.cpp(58)' : 'f'  [may be found via
> argument-dependent lookup]
>
>   g(S()); // warning C4239: nonstandard extension used : 'argument' :
> conversion from 'S' to 'S &'
>

Presumably this is accepted if you use g(T) not g(T&) on line 4?


>   g<S>(S{}); // error C2143: syntax error : missing ')' before '{'
>

Is this accepted if you use S() not S{} ?

  g<int>(0); // error C3767: 'g': candidate function(s) not accessible \
>              // could be the friend function at
> 'friend_functions_inline.cpp(59)' : 'g'  [may be found via
> argument-dependent lookup]
> }
>
> *Test 2: Added variables f & g*
>
> int f, g;
>
> class S {
> public:
>   friend void f() {} // error C2365: 'f' : redefinition; previous
> definition was 'data variable'
>   template<typename T> friend void g(T&) {} //
> friend_functions_inline.cpp(61) : error C2365: 'g' : redefinition; previous
> definition was 'data variable' \
>    // friend_functions_inline.cpp(56) : see declaration of 'g' \
>    // friend_functions_inline.cpp(61) : error C2904: 'g' : name already
> used for a template in the current scope \
>    // friend_functions_inline.cpp(56) : see declaration of 'g'
> };
> void h() {
>   f();          // error C2064: term does not evaluate to a function
> taking 0 arguments
>   g(S()); // error C2064: term does not evaluate to a function taking 1
> arguments
>   g<S>(S{}); // [various errors - template not resolved]
>   g<int>(0); // error C2062: type 'int' unexpected
>  }
>
> *Test 3: Enclosing namespace*
> *
> *
> This results in the same output as test 2 but with the namespace
> qualification in the errors.
>

Some more test cases:

1)

int f;
namespace N {
  class S {
    template<typename T> friend void f(T) {}
  };
  void g() {
    f(S());
    f<S>(S());
    f(0);
    f<int>(0);

    int k = f;
  }
}

2)

class S {
  template<typename T> friend void f(T) {}
};
namespace N {
  int f;
  void g() {
    f(S());
    f<S>(S());
    f(0);
    f<int>(0);
  }
}

3)

namespace M {
  class S {
    template<typename T> friend void f(T) {}
  };
}
void g() {
  f(M::S());
  f<M::S>(M::S());
  f(0);
  f<int>(0);
}

I hope that provides some insight.
>
> - Will.
>
>
> On 9 July 2013 23:46, Richard Smith <richard at metafoo.co.uk> wrote:
>
>> On Tue, Jul 9, 2013 at 2:32 PM, Will Wilson <will at indefiant.com> wrote:
>> > Thanks Richard. [temp.arg.explicit]p8 uses namespaces in the example
>> which
>> > threw me. Anyhow, I'll take a look at adding support for this when in MS
>> > mode. I assume it shouldn't be too hard to do...?
>>
>> Does MSVC perform friend injection in general, or does it just somehow
>> manage to parse DoT as a template name in this case? For instance:
>>
>> struct S {
>>   friend void f() {}
>>   template<typename T> friend void g(T) {}
>> };
>> void h() {
>>   f(); // ok?
>>   g(S()); // ok?
>>   g<S>(S{}); // ok?
>>   g<int>(0); // ok?
>> }
>>
>> ... and what happens if you add:
>>
>>   int f, g;
>>
>> prior to the class definition? What happens if you add them to an
>> enclosing namespace?
>>
>> > On 9 July 2013 22:17, Richard Smith <richard at metafoo.co.uk> wrote:
>> >>
>> >> On Tue, Jul 9, 2013 at 8:38 AM, Will Wilson <will at indefiant.com>
>> wrote:
>> >> > Hi All,
>> >> >
>> >> > A quick question regarding correct behaviour:
>> >> >
>> >> > class Vec3 {
>> >> > public:
>> >> > friend void DoA(Vec3& a) {
>> >> > a.m_int = 1;
>> >> > }
>> >> >
>> >> > template <const bool B>
>> >> > friend void DoT(Vec3& a) {
>> >> > if (B)
>> >> > a.m_int = 2;
>> >> > }
>> >> > private:
>> >> > int m_int;
>> >> > };
>> >> >
>> >> > void test_friend_functions_inline() {
>> >> > Vec3 a;
>> >> > DoA(a);
>> >> > DoT<true>(a);  // error: use of undeclared identifier 'DoT'
>> >>
>> >> Lookup of DoT here finds nothing, so this is parsed as a comparison
>> >> rather than as a template. EDG rejects this in its strict mode.
>> >>
>> >> See [temp.arg.explicit]p8, which has almost exactly this case as an
>> >> example.
>> >
>> >
>> >
>> >
>> > --
>> > Indefiant Ltd.
>> >
>> > Firsby Lodge, New Main Road, Scamblesby, Louth, Lincs LN11 9XH UK
>> > Tel: +44 20 8123 7663 England Registered No. 07936820 VAT No. 128556202
>>
>
>
>
> --
> *Indefiant Ltd.*
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130827/5cf154b1/attachment.html>


More information about the cfe-dev mailing list