2016-06-17 5 views
7

Tak było odpowiedzi na to pytanie: Define friend function template of class template i znalazłem jakieś „dziwne” zachowanie z g ++ (5.3) i szczęk (3.8):Powrót typ mecz z auto i znajomych funkcji

załóżmy następujący szablon :

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

to skompilować zarówno kompilatora (zgodnie z oczekiwaniami - Jeśli to nie powinno skompilować, prosimy o komentarz i wyjaśnienie dlaczego).

Jeśli zmienię rzeczy:

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) { /* ... */ } 

to skompilować z g ++, ale nie z hukiem, a jeśli ustawić jeden do auto a drugi do określonej wartości, np

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) { /* ... */ } 

Oba kompilatory odrzucają kod, który mówi:

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

Moje dwa powiązane pytania to:

  • Który kompilator jest odpowiedni dla pierwszego przypadku (auto dla deklaracji/definicji)?
  • Dlaczego nie można użyć auto podczas definiowania funkcji i test<K> podczas deklarowania przyjaźni?

lub w jednym pytaniu: Jakie są zasady przyjmowania zgłoszeń o auto funkcyjnych przyjaciel gdy funkcja jest zdefiniowana poza klasą?

Odpowiedz

4

Rozważmy [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.

Tj jeśli deklaracja przyjaciela używa auto, a druga deklaracja nie, nie pasują do siebie. Odwrotnie jest gwarantowana przez core issue 2081. Wreszcie, jeśli oba używają auto, deklaracje powinny rzeczywiście pasować zgodnie z [temp.over.link]/6, więc Clang jest w tym przypadku niepoprawny.