Return type with auto and friend function

So, I answered this question: Define a friends function template for a class template , and I found some "weird" behavior from g ++ (5.3) and clang (3.8)

Assume the following pattern:

template<int M> struct test { private: int value; template<int U, int K> friend test<K> foo (test<U> const t); }; template <int M, int N = 2 * M> test<N> foo (test<M> const t) { test<N> r; r.value = t.value; return r; } int main(){ test<1> t; foo(t); } 

Compile both compilers (as expected - if this should not compile, feel free to comment and explain why).

If I changed things to:

 template<int U, int K> friend auto foo(test<U> const t); template <int M, int N = 2 * M> auto foo (test<M> const t) { /* ... */ } 

This compiler is with g ++, but not with clang, and if I set it to auto and the other to a specific value, for example:

 template<int U, int K> friend test<K> foo(test<U> const t); template <int M, int N = 2 * M> auto foo (test<M> const t) { /* ... */ } // or: template<int U, int K> friend auto foo(test<U> const t); template <int M, int N = 2 * M> test<N> foo (test<M> const t) { /* ... */ } 

Both compilers reject the code saying that:

error: 'int test <2> :: value' is private

My two related questions:

  • Which compiler is right for the first case ( auto for declaration / definition)?
  • Why can't auto be used when defining a function and test<K> when declaring friendship?

Or in one question: What are the auto rules for declaring friend functions when a function is defined outside the class?

+7
c ++ language-lawyer friend c ++ 14 auto
source share
1 answer

Consider [dcl.spec.auto] / 13 :

The declarations or specializations of a function template or function with a declared return type that uses a placeholder type should also use that placeholder, not the deduced type.

those. if auto used in a friend’s ad and the second ad is not, they do not match. Another way is guaranteed by the main problem of 2081 . Finally, if both use auto , the declarations really have to match [temp.over.link] / 6 , so Clang is wrong in this case.

+4
source share

All Articles