如何使用 clang 将模板类的构造函数声明为友元?(使用 g++ 编译,而不是 clang++)

Eri*_*ric 7 c++ clang++

我有一个带有私有构造函数的模板类,它是该类的每个类型实例的朋友。以下在 g++ 11.4.0 下编译,但在 clang++ 版本 14.0.0-1ubuntu1.1 下失败

template <typename T>
class foo {
    foo(T){}
    template <typename U> friend foo<U>::foo(U);

    public:
    foo(){}
};

int main() {
    foo<int> a{};
}
Run Code Online (Sandbox Code Playgroud)

clang 给出了错误

main.cpp:4:34: error: missing 'typename' prior to dependent type name 'foo<U>::foo'
    template <typename U> friend foo<U>::foo(U);
                                 ^~~~~~~~~~~
                                 typename
main.cpp:4:46: error: friends can only be classes or functions
    template <typename U> friend foo<U>::foo(U);
Run Code Online (Sandbox Code Playgroud)

我不认为foo<U>::foo是依赖类型名称,但无论如何按照建议添加类型名称会导致错误

main.cpp:4:55: error: friends can only be classes or functions
    template <typename U> friend typename foo<U>::foo(U);
Run Code Online (Sandbox Code Playgroud)

eca*_*mur 3

这似乎是 clang 中的编译器错误。如果我们看一下相关的情况,其中被友好的类模板构造函数属于不同的非模板类:

template<class T>
struct X {
    X(T);
};
class C {
    template<class U> friend X<U>::X(U);
    C();
};
template<class T> X<T>::X(T) { C c; }
X<int> x(1);
Run Code Online (Sandbox Code Playgroud)

这为 clang 的行为提供了线索;它接受并带有警告:

警告:不支持友元类声明的依赖嵌套名称说明符“X::”;关闭“C”的访问控制 [-Wunsupported-friend]

因此,clang 缺少这方面的支持,并且在被友好的构造函数属于类模板的情况下没有意识到这一点(至少能够发出警告)。

最简单的解决方法可能是遵循https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42328#c4的建议并与全班同学交朋友:

    template <typename U> friend class foo;
Run Code Online (Sandbox Code Playgroud)