2016-06-17 9 views
7

Так что я отвечал на этот вопрос: Define friend function template of class template, и я нашел «странное» поведение от г ++ (5.3) и лязг (3.8):Возвращение с автоматическим и друг функции

Давайте предположим следующий шаблон :

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

Это компилировать как с компилятором (как и следовало ожидать - если это не должно составить, не стесняйтесь комментировать и объяснять, почему).

Если я изменяю вещи:

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

Это компилировать с г ++, но не с грохотом, и если я установить один к auto, а другой к определенному значению, например:

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

И компилятор отвергает код говоря, что:

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

две мои смежные вопросы являются:

  • Какой компилятор подходит для первого случая (auto для декларации/определения)?
  • Почему не удается использовать auto при определении функции и test<K> при объявлении дружбы?

Или один вопрос: Каковы правила о auto для объявления функций друга, когда функция определена вне класса?

ответ

4

Рассмотрим [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.

Т.е. если декларация друга использует auto, а вторая декларация не соответствует, они не совпадают. Другой способ гарантируется core issue 2081. Наконец, если оба используют auto, объявления должны действительно соответствовать [temp.over.link]/6, поэтому Clang неверен в этом случае.