提问人:Jay 提问时间:11/11/2023 最后编辑:user12002570Jay 更新时间:11/11/2023 访问量:102
嵌套在模板类 C++ 中的非模板化类
Nested not templated class inside a template class C++
问:
这是我的代码
头.h
template <class T>
class Ext;
template <class T>
void fun(const Ext<T>&);
template <class T>
class Ext {
friend void fun<T>(const Ext<T>&);
private:
class Inner;
Inner* p;
};
template <class T>
void fun2(const typename Ext<T>::Inner&);
template <class T>
class Ext<T>::Inner {
friend class Ext<T>;
friend void fun<T>(const Ext<T>&);
friend void fun2<T>(const typename Ext<T>::Inner&);
private:
Inner* q;
int a;
Inner() : a(1) {}
};
template <class T>
void fun2(const typename Ext<T>::Inner& i) {
std::cout << i.a << std::endl;
}
template <class T>
void fun(const Ext<T>& e) {
typename Ext<T>::Inner y;
y.a = 3;
fun2<T>(y);
}
main.cpp
int main() {
Ext<int> x;
fun(x);
}
g++ 和(见下文)clang 给出一个
class Ext<int>::Inner’ is private within this context
所以我的问题是:有没有办法在不公开内部阶级的情况下做到这一点? 为什么如果我用重载运算符替换 fun anf fun2<<那么它甚至可以使用内部类 private(仅使用 CLANG)进行编译?喜欢这个
头.h
#include <iostream>
template <class T>
class Ext;
template <class T>
std::ostream& operator<<(std::ostream&, const Ext<T>&);
template <class T>
class Ext {
friend std::ostream& operator<< <T>(std::ostream&, const Ext<T>&);
private:
class Inner;
Inner* p;
};
template <class T>
std::ostream& operator<<(std::ostream&, const typename Ext<T>::Inner&);
template <class T>
class Ext<T>::Inner {
friend class Ext<T>;
friend std::ostream& operator<< <T>(std::ostream&, const typename Ext<T>::Inner&);
private:
Inner* q;
int a;
Inner() : a(1) {}
};
template <class T>
std::ostream& operator<<(std::ostream& os, const typename Ext<T>::Inner& n) {
return os << n.a << " ";
}
template <class T>
std::ostream& operator<<(std::ostream& os, const Ext<T>& t) {
os << "[ ";
operator<< <T>(os, *(t.p));
os << "] ";
return os;
}
main.cpp
int main() {
Ext<int> x;
std::cout << x << std::endl;
}
我尝试使用不同的编译器进行编译,但如果我不使用 clang 进行编译,则没有任何效果,在这种情况下,它仅在函数是运算符的重载时进行编译
答:
1赞
user12002570
11/11/2023
#1
有没有办法在不公开内部阶级的情况下做到这一点?
是的,但是代码存在几个问题,下面将解释和解决所有这些问题。
首先,ship 在 C++ 中不是关联的。这意味着您需要在类模板内部添加一个友元模板声明,如下面的代码所示。friend
fun2
Ext
其次,您当前拥有的好友声明是非模板好友声明。但是,由于 和 是模板,因此您需要将它们更改为友元模板声明,这是通过添加如下所示的代码来完成的。fun
fun2
template<typename U>
注释也添加到下面的程序中,以便更容易发现更改:
#include <iostream>
template <class T>
class Ext;
template <class T>
void fun(const Ext<T>&);
template <class T>
class Ext {
template<typename U> //added this template<typename U>
friend void fun(const Ext<U>&);
//added this friend template declaration
template <class U>
friend void fun2(const typename Ext<U>::Inner& i);
private:
class Inner;
Inner* p;
};
template <class T>
void fun2(const typename Ext<T>::Inner&);
template <class T>
class Ext<T>::Inner {
template<typename U> //added this template<typename U>
friend void fun(const Ext<U>&);
template <class U> //added this template<typename U>
friend void fun2(const typename Ext<U>::Inner& i);
private:
Inner* q;
int a;
Inner() : a(1) {}
};
template <class T>
void fun2(const typename Ext<T>::Inner& i) {
std::cout << i.a << std::endl;
}
template <class T>
void fun(const Ext<T>& e) {
typename Ext<T>::Inner y;
y.a = 3;
fun2<T>(y);
}
int main() {
Ext<int> x;
fun(x);
}
现在该程序适用于所有编译器。
评论
0赞
Jay
11/12/2023
是的,但是如果我做 fun 和 fun2 friend 模板声明,那么无论模板参数如何,它们都是 Ext 的朋友。
评论
Ext
template<typename U>