具有自动和友元功能的返回类型匹配

Return type match with auto and friend function

本文关键字:返回类型 功能 友元      更新时间:2023-10-16

所以我在回答这个问题:定义类模板的友元函数模板,我从 g++ (5.3) 和 clang (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) { /* ... */ }

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

两个编译器都拒绝代码,指出:

错误:"int test<2>::value"是私有

我的两个相关问题是:

  • 哪个编译器适合第一种情况(auto声明/定义)?
  • 为什么在定义函数时不能使用auto,在声明友谊时不能使用test<K>

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

考虑 [dcl.spec.auto]/13:

函数或

函数模板的重新声明或专用化 对于使用占位符类型的声明返回类型,还应 使用该占位符,而不是推导类型。

即,如果朋友声明使用auto而第二个声明不使用,则它们不匹配。相反,核心问题 2081 保证。最后,如果两者都使用auto,则声明确实应该按照 [temp.over.link]/6 匹配,因此 Clang 在这种情况下是不正确的。