E
Erik
private and protected members can only be accessed by deriving a class
or by giving friendship. The problem with friendship is that friend
statements are written inside the class. A FriendShip Policy solves the
problem.
There are different proposals how to solve the problem: The first idea
is to provide the class with a macro
---------------------------------------------------------------------
#define FRIENDS_OF_FOO class A; class B; class C
class foo
{
friends FRIENDS_OF_FOO;
private:
int pfoo;
};
The classes A,B and C can now access the private member pfoo;
-----------------------------------------------------------------------------------------------------------------------------
Because I don't like macros I was looking for an generic
implementation. My first attempt looks like that:
template <class T>
class foo
{
friends T;
private: int pfoo;
};
class A
{
foo<A> myFoo;
};
class B
{
foo<B> myFoo;
}
class D
{
A a;
B b;
}
The solution above has several disadvantage:
- The compiler generates a class for each different template parameter
- class A,B cannot share class foo. because there are different types
of foo.
- To provide the class foo with more template parameter seemed not to
be an adequat way
- This is not legal C++ (some compilers refuse that code)
-----------------------------------------------------------------------------------------------------------------------------
The attemped is to use TYPELSIST from the Loki Library (Reference:
Modern C++ Design by Andrei Alexandrescu) hopefully removes the
restriction on friendship.
The policy is provided with a macro and a Typlist as template parameter
//header of friendship.hpp
#include "Loki/TypeList.h"
#include "Loki/EmptyType.h"
#define MAKE_FRIENDS(x= x:arm1 ; friend x:arm2; friend x:arm3;
..... friend x:arm51
template <class TList=Loki::EmptyType> class FriendShip
{
public:
typedef typename TList:armList;
typedef typename Loki::TL::TypeAtNonStrict<TList, 0,
Loki::EmptyType>::Result Parm1;
typedef typename Loki::TL::TypeAtNonStrict<TList, 2,
Loki::EmptyType>::Result Parm2;
...
typedef typename Loki::TL::TypeAtNonStrict<TList, 50,
Loki::EmptyType>::Result Parm51;
};
//end of header friendship.hpp
-----------------------------------------------------------------------------------------------------------------------------
How can the policy be used? First we have to modify class foo:
template <class Friends_Of_Foo>
class foo
{
friends MAKE_FRIENDS(Friends_Of_Foo);
private:
int pfoo;
};
See below how foo can be used:
typedef FriendShip<TYPELIST_3(A,B,C)> friends_of_foo;
class A
{
foo<friends_of_foo> Foo;
};
class B
{
foo<friends_of_foo> Foo;
};
class D
{
A a;
B b;
};
Now the class foo is adaptable and can be generically used.
I used friendship policies to encapsulate functors in dll-Libraries.
I'm not sure, if this is legal C++ code. The compilers I used accept
this code.
-----------------------------------------------------------------------------------------------------------------------------
or by giving friendship. The problem with friendship is that friend
statements are written inside the class. A FriendShip Policy solves the
problem.
There are different proposals how to solve the problem: The first idea
is to provide the class with a macro
---------------------------------------------------------------------
#define FRIENDS_OF_FOO class A; class B; class C
class foo
{
friends FRIENDS_OF_FOO;
private:
int pfoo;
};
The classes A,B and C can now access the private member pfoo;
-----------------------------------------------------------------------------------------------------------------------------
Because I don't like macros I was looking for an generic
implementation. My first attempt looks like that:
template <class T>
class foo
{
friends T;
private: int pfoo;
};
class A
{
foo<A> myFoo;
};
class B
{
foo<B> myFoo;
}
class D
{
A a;
B b;
}
The solution above has several disadvantage:
- The compiler generates a class for each different template parameter
- class A,B cannot share class foo. because there are different types
of foo.
- To provide the class foo with more template parameter seemed not to
be an adequat way
- This is not legal C++ (some compilers refuse that code)
-----------------------------------------------------------------------------------------------------------------------------
The attemped is to use TYPELSIST from the Loki Library (Reference:
Modern C++ Design by Andrei Alexandrescu) hopefully removes the
restriction on friendship.
The policy is provided with a macro and a Typlist as template parameter
//header of friendship.hpp
#include "Loki/TypeList.h"
#include "Loki/EmptyType.h"
#define MAKE_FRIENDS(x= x:arm1 ; friend x:arm2; friend x:arm3;
..... friend x:arm51
template <class TList=Loki::EmptyType> class FriendShip
{
public:
typedef typename TList:armList;
typedef typename Loki::TL::TypeAtNonStrict<TList, 0,
Loki::EmptyType>::Result Parm1;
typedef typename Loki::TL::TypeAtNonStrict<TList, 2,
Loki::EmptyType>::Result Parm2;
...
typedef typename Loki::TL::TypeAtNonStrict<TList, 50,
Loki::EmptyType>::Result Parm51;
};
//end of header friendship.hpp
-----------------------------------------------------------------------------------------------------------------------------
How can the policy be used? First we have to modify class foo:
template <class Friends_Of_Foo>
class foo
{
friends MAKE_FRIENDS(Friends_Of_Foo);
private:
int pfoo;
};
See below how foo can be used:
typedef FriendShip<TYPELIST_3(A,B,C)> friends_of_foo;
class A
{
foo<friends_of_foo> Foo;
};
class B
{
foo<friends_of_foo> Foo;
};
class D
{
A a;
B b;
};
Now the class foo is adaptable and can be generically used.
I used friendship policies to encapsulate functors in dll-Libraries.
I'm not sure, if this is legal C++ code. The compilers I used accept
this code.
-----------------------------------------------------------------------------------------------------------------------------