这是我的代码
head.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
型
所以我的问题是:有没有一种方法可以做到这一点,而不使内部类公开?为什么如果我用重载操作符<<替换funanf fun2,那么即使内部类私有(仅与CLANG)编译?像这样
head.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条答案
按热度按时间l0oc07j21#
有没有一种方法可以做到这一点,而不使内部类公开?
是的,但是代码中有几个问题,所有这些问题都在下面解释和solved。
首先,
friend
ship在C++中是不关联的。这意味着您需要在类模板Ext
中为fun2
添加一个 friend template declaration,如下面的代码所示。其次,您目前拥有的friend声明是 * 非模板friend声明 *。但由于
fun
和fun2
是模板,您需要将其更改为friend模板声明,这可以通过在下面的代码中添加template<typename U>
来完成。下面的程序中也添加了注解,以便更容易发现更改:
字符串
Working demo的
现在程序可以与所有编译器一起工作。