模板类中嵌套的非模板化类C++

w3nuxt5m  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(99)

这是我的代码
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编译,那么什么都不起作用,在这种情况下,它只在函数是运算符的重载时编译。

l0oc07j2

l0oc07j21#

有没有一种方法可以做到这一点,而不使内部类公开?
是的,但是代码中有几个问题,所有这些问题都在下面解释和solved

首先friend ship在C++中是不关联的。这意味着您需要在类模板Ext中为fun2添加一个 friend template declaration,如下面的代码所示。
其次,您目前拥有的friend声明是 * 非模板friend声明 *。但由于funfun2是模板,您需要将其更改为friend模板声明,这可以通过在下面的代码中添加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);
}

字符串
Working demo
现在程序可以与所有编译器一起工作。

相关问题