c++ - 具有不同模板参数的相同类不能访问彼此的私有(private)字段

标签 c++ templates friend

我有一个模板类 my_class<T>它正在接收构造函数参数 my_class<U> (通常具有不同的模板参数)。 与没有模板或具有相同模板参数的代码不同,我无法访问 my_class<U>实例私有(private)字段,但它是同一个类。

template <class T>
class my_class {

    private:            
       T * data;

    public: 
        template <class U>
        my_class(const my_class<U> & p) {
            data = p.data; // <-- visibility exposing
        }
}

有什么技巧可以让它成为可能吗?也许我可以用不同的模板参数定义一个友元类?

最佳答案

回答您的评论:“只有当 U 是 T 的 child 时它才有效。有什么办法可以做到这一点吗?”..使用特征..这将帮助您确定 U 是否源自 T..

具有以下特征,以下是使用它们的函数的允许参数:

/**
    Arguments can be (is_non_class_same<T, U>::value):
        T = T     -> U = T for any class.
        T = void* -> U = any non-class pointer.
        T = int*  -> U = int*. U cannot be a float*. Incompatible pointers.
        T = int   -> U = float
        T = double -> U = float or int.  Valid.. double is large enough to hold float and int.
        T = int   -> U = double  Invalid.. double is larger than type float.. loss of precision.
        T = float -> U = double  Invalid.. double is larger than type float.. loss of precision.

    Arguments can be (is_class_same<T, U>::value, U>::type):

        T = Base* -> U = Base*.
        T = Base* -> U = Derived*
        T = Base  -> U = Derived  Invalid.. See: Slicing Problem.
**/

示例(工作代码):http://ideone.com/dHZhHc <-- 活生生的例子..

#include <type_traits>
#include <memory>
#include <iostream>

template<typename T, typename U>
struct is_non_class_same : public std::integral_constant<bool, (!std::is_base_of<
        typename std::remove_pointer<T>::type,
        typename std::remove_pointer<U>::type>::value &&
        std::is_convertible<U, T>::value && sizeof(T) >= sizeof(U)) ||
(std::is_class<T>::value && std::is_class<U>::value &&
 !std::is_pointer<T>::value && !std::is_pointer<U>::value &&
 std::is_same<T, U>::value)>
{};

template<typename T, typename U>
struct is_class_same : public std::integral_constant<bool, std::is_base_of<
        typename std::remove_pointer<T>::type,
        typename std::remove_pointer<U>::type>::value &&
        std::is_pointer<T>::value>
{};


class Node
{
protected:
    Node* previous;
    Node* next;

    Node() : previous(nullptr), next(nullptr) {}

    template<class T, class TD>
    friend class linked_ptr;

public:
    virtual ~Node() {}

};

template<typename T, typename TD = typename std::remove_pointer<T>::type>
class linked_ptr : public Node
{
private:
    template<class, class> friend class linked_ptr; /** Access friend level **/
    T data;

public:

    template<class U, typename TU = typename std::remove_pointer<U>::type, typename = typename std::enable_if<is_non_class_same<T, U>::value || is_class_same<T, U>::value, U>::type>
    linked_ptr(U data) : data(data) {}
    ~linked_ptr();

    template<class U, typename TU = typename std::remove_pointer<U>::type, typename = typename std::enable_if<is_non_class_same<T, U>::value || is_class_same<T, U>::value, U>::type>
    void setData(U data)
    {
        this->data = data;
    }

    template<class U, typename TU = typename std::remove_pointer<U>::type, typename = typename std::enable_if<is_non_class_same<T, U>::value || is_class_same<T, U>::value, U>::type>
    void append(U data);
};

template<typename T, typename TD>
linked_ptr<T, TD>::~linked_ptr()
{
    TD(data);
    delete this->next;
}

template<typename T, typename TD>
template<typename U, typename TU, class>
void linked_ptr<T, TD>::append(U data)
{
    if (!this->next)
    {
        this->next = new linked_ptr<U>(data);
        this->next->previous = this;
        return;
    }

    Node* t = this->next;
    while(t->next != nullptr)
    {
        t = t->next;
    }

    t->next = new linked_ptr<U>(data);
}




class foo
{
public:
    virtual ~foo()
    {
        std::cout<<"destroyed foo\n";
    };

    virtual void print()
    {
        std::cout<<"foo\n";
    }
};

class bar : public foo
{
public:
    virtual ~bar()
    {
        std::cout<<"destroyed bar\n";
    }

    virtual void print()
    {
        std::cout<<"bar\n";
    }
};

int main()
{
    linked_ptr<foo*> list(new foo());
    list.append(new bar());
    list.append(new bar());
    list.append(new foo());
}

关于c++ - 具有不同模板参数的相同类不能访问彼此的私有(private)字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27433533/

相关文章:

c++ - 如何检查模板特化是否是基模板的子类?

c++ - C++中具有友元函数的多态性

c++ - 按位置查找未标记的模板选项/参数/参数

php - 如何制作动态wordpress页面(自定义控件/页面模板框)

c++ - 如何在 OS X 上获取 C++ 手册页?

c++ - <void(void)> 在模板参数中的含义

c++ - 我怎样才能在基类中成为派生类函数的 friend ?

c++ - Friend ostream& operator<< 无法访问私有(private)成员

c++ - 录像机的多线程

c++ - 动态数组与 std::vector