Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return type match with auto and friend function

So I was answering this question: Define friend function template of class template, and I found some "weird" behavior from g++ (5.3) and clang (3.8):

Let's assume the following template:

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);
}

This compile with both compiler (as expected - If this should not compile, feel free to comment and explain why).

If I change 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 compile with g++ but not with clang, and if I set one to auto and the other one to a specific value, e.g.:

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 compiler reject the code saying that:

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

My two related questions are:

  • Which compiler is right for the first case (auto for both declaration/definition)?
  • Why is not possible to use auto when defining the function and test<K> when declaring the friendship?

Or in one question: What are the rules about auto for friend function declarations when the function is defined outside the class?

like image 417
Holt Avatar asked Jun 17 '16 13:06

Holt


1 Answers

Consider [dcl.spec.auto]/13:

Redeclarations or specializations of a function or function template with a declared return type that uses a placeholder type shall also use that placeholder, not a deduced type.

I.e. if the friend declaration uses auto and the second declaration does not, they don't match. The other way around is guaranteed by core issue 2081. Finally, if both use auto, the declarations should indeed match as per [temp.over.link]/6, so Clang is incorrect in that case.

like image 160
Columbo Avatar answered Oct 02 '22 14:10

Columbo