I am looking for a solution to the following problem:
I have a class X
with (assuming) only protected
members. And I have a set S of several classes A
, B
, C
, ...
Assuming there is an existing instance x
of class X
members (which instance may be, either an instance of class X
, or a subset of an instance of any suitable container/derived-class/... depending on class X
) :
s
of a class of the set S, in relation with (depending on) x
, must have access to protected
members of x
.protected
members of x
must be restricted to s
(and x
).s
must keep instance x
alive and unaltered.Additionally, at a given time, only one instance s
[in relation] with x
is existing.
In other words and to clarify the above requirements: I need that any instance s
have access to protected
members of class X
, just like if (for example) classes of the set S were publicly derived from X
, except that the subset of members coming from class X
in inheritance must remain alive and unaltered whether instance s
is created or destroyed.
In addition, the following requirements must be met:
X
must be considered non-copyable and non-movable.protected
members of X
, though acceptable, is not desirable due to maintenance cost.S
friends of X
is obviously not acceptable (to many classes).The currently implemented solution, that though does not fulfills requirement #5, is using composition and a parent class for classes of S friend of X
, e.g.:
class X
{
// public: int get_prot(); // not allowed (rq#2)
protected: int prot;
friend class Xaxx;
// friend A; friend B; ... // not acceptable (rq#6)
};
class Xacc
{
protected:
Xacc(X& x) : x(x) {}
int& x_prot() { return x.prot; } // not desirable (rq#5)
X& x;
};
class A : public Xacc
{
public:
A(X& x) : Xacc(x) {}
void work() { x_prot() = 1; }
};
Another interesting solution tested, that fulfills all requirements expect #4 though:
class A : public X
{
public:
A(const X& x) : X(x) {} // X not copyable (rq#4)
void work() { prot = 1; }
};
Any solution up to C++14 is acceptable. Thanks for your help.
Rationale:
To clarify where this problem comes from and in which way a solution will help me improve my code:
X
) which implements all sort of works (algorithms, i/o, and so on...)X
must not be altered in this switch.If your classes in S have a uniform interface that is simple (e.g. a single 'work' method), you can change your current implementation to fulfill requirement #5 by making Xacc a template class and by moving the implementation of the access to the protected parts of X into the specializations of Xacc. It would look like this:
class X
{
protected:
int prot;
template<typename State> friend class Xacc;
};
template<class State>
class Xacc
{
public:
Xacc(X &x) : x(x) {}
void work();
private:
X &x;
};
class S1;
template<> void Xacc<S1>::work()
{
x.prot = 1;
};
class S1: public Xacc<S1>
{
public:
S1(X &x): Xacc<S1>(x) {}
protected:
};