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

问题描述 投票:0回答:1

我有一个带有私有构造函数的模板类,我希望该私有构造函数成为该类的所有模板化实例的朋友。以下在 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{};
}

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

我不认为

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

main.cpp:4:55: error: friends can only be classes or functions
    template <typename U> friend typename foo<U>::foo(U);
c++ clang++
1个回答
0
投票

这似乎是编译器错误的集合。注意,gcc 实际上是无效的;如果您实际上尝试从假定的友好构造函数访问私有实体,它会拒绝:

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

    public:
    foo(){ foo<long> f(1l); }
//                   ^
// error: 'foo<T>::foo(T) [with T = long int]' is private within this context
};
int main() {
    foo<int> a{};
}

但是,如果您从构造函数中删除参数列表,gcc 会奇怪地接受:

template <typename T>
class foo {
    foo(T);
    template <typename U> friend foo<U>::foo();
//                                           ^ removed 'U'

    public:
    foo(){ foo<long> f(1l); }
};
int main() {
    foo<int> a{};
}

此外,gcc 接受相关代码,其中被友好的类模板构造函数属于不同的类模板:

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

(也许 bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59798 相关;我不确定。)

gcc 还接受被友好的类模板构造函数属于不同的非模板类:

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

最后一个代码是 clang 行为的线索;接受并带有警告:

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

所以,clang 在这方面缺少支持并且没有意识到这一点。

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

    template <typename U> friend class foo;
© www.soinside.com 2019 - 2024. All rights reserved.