Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template composition and friendship transitivity

I have container with private data and friend class that access private data:

template<class T>
class Container
{
    friend typename T::MyAccessor;
    vector<T> _data;
};

template<class T>
class Accessor
{
public:
    void doSomething(Container<T> *c)
    {
        cout << c->_data.size() << endl;
    }
};

template<class T, template<typename> class CustomAccessor>
struct MyBase
{
    typedef Container<T> MyContainer;
    typedef CustomAccessor<T> MyAccessor;
};

Now I want to make a composition of accessors this way:

template<
    template<typename> class First
    ,template<typename> class Second 
    ,class T
>
class Composite
{
public:
    typedef First<T> MyFirst;
    typedef Second<T> MySecond;

    void doSomething(Container<T> *c)
    {
        MyFirst a;
        a.doSomething(c);

        MySecond b;
        b.doSomething(c);
    }
};

template<class T>
class DoubleAccessor : public Composite<Accessor, Accessor, T> {};

but friendship is not transitive and composed accessors cant access container private data. Is there a way around this without exposing container private data for everybody?

like image 290
Dmitry Teslenko Avatar asked Jan 29 '26 16:01

Dmitry Teslenko


1 Answers

What if you just declare the class Accessor as a friend of your class Container:

template<class T>
class Container {
    template<class T1> friend class Accessor;
    std::vector<T> _data;
};

template<class T>
class Accessor {
public:
    void doSomething(Container<T> *c) {
        std::cout << c->_data.size() << std::endl;
    }
};

template<class T, template<typename> class CustomAccessor = Accessor>
struct MyBase {
    typedef Container<T> MyContainer;
    typedef CustomAccessor<T> MyAccessor;
};

template<class T, template<typename> class First = Accessor, template<typename> class Second = Accessor>
class Composite {
public:
    typedef First<T> MyFirst;
    typedef Second<T> MySecond;

    void doSomething(Container<T> *c) {
        MyFirst a;
        a.doSomething(c);

        MySecond b;
        b.doSomething(c);
    }
};

LIVE DEMO

like image 176
101010 Avatar answered Feb 01 '26 05:02

101010