提问者:小点点

返回类型匹配与自动和朋友功能


所以我在回答这个问题:定义类模板的朋友函数模板,我发现一些奇怪的行为从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测试

我的两个相关问题是:

  • 哪种编译器适用于第一种情况(auto适用于两种声明/定义)
  • 定义功能和测试时,为什么不能使用auto

或者在一个问题中:当函数定义在类之外时,朋友函数声明的自动规则是什么?


共1个答案

匿名用户

考虑[DCL,SPEC.AUTO ] / 13:

具有声明的返回类型且使用占位符类型的函数或函数模板的重新声明或专门化也应使用该占位符,而不是推导的类型。

也就是说,如果朋友声明使用了auto,而第二个声明不使用,则它们不匹配。另一方面,核心发行2081保证了这一点。最后,如果两者都使用auto,则声明应该按照[temp.over.link]/6匹配,因此在这种情况下,Clang是不正确的。