Return 使用自动和友元函数进行类型匹配

Return type match with auto and friend function

所以我在回答这个问题:Define friend function template of class template,我从 g++ (5.3) 和 clang (3.8) 中发现了一些 "weird" 行为:

让我们假设以下模板:

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

这是用 g++ 编译的,但不是用 clang 编译的,如果我将一个设置为 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

我的两个相关问题是:

或者在一个问题中:当函数定义在 class 之外时,关于 auto 友元函数声明的规则是什么?

考虑 [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. Finally, if both use auto, the declarations should indeed match as per [temp.over.link]/6 保证了另一种方式,因此在这种情况下 Clang 是不正确的。