Type specific flags in a class hierarchy

M

Marco Nef

Hi there,

I'm trying to do something like the following:

template<class TYPE> class CFlags
{
public:
VOID AddFlag(TYPE eFlag);
VOID RemoveFlag(TYPE eFlag);
};

class CClass1 : public CFlags<CClass1::EFlags>
{
public:
typedef enum EFlags
{
...
} EFlags;
};

class CClass2 : public CClass1,public CFlags<CClass2::EFlags>
{
public:
typedef enum EFlags
{
...
} EFlags;
};

I know that this cannot work because the EFlags are not known where needed.
I've tried many things, but none was a nice solution or worked at all (I
prefer a real C++ solution, which means there should be no macros).

Does anyone have an idea how to solve the following problems in a nice C++
way?

- EFlags should not be in global space
- Each class in a hierarchy may have its own flags
- The flags must be type specific

Thanks,
Marco

_____________________________

()() Marco Nef
( '.')
(")_(") http://www.shima.ch/marco/
 
M

Michael DOUBEZ

Marco Nef a écrit :
Hi there,

I'm trying to do something like the following:

template<class TYPE> class CFlags
{
public:
VOID AddFlag(TYPE eFlag);
VOID RemoveFlag(TYPE eFlag);
};

class CClass1 : public CFlags<CClass1::EFlags>
{
public:
typedef enum EFlags
{
...
} EFlags;
};

class CClass2 : public CClass1,public CFlags<CClass2::EFlags>
{
public:
typedef enum EFlags
{
...
} EFlags;
};

I know that this cannot work because the EFlags are not known where needed.
I've tried many things, but none was a nice solution or worked at all (I
prefer a real C++ solution, which means there should be no macros).

Does anyone have an idea how to solve the following problems in a nice C++
way?

- EFlags should not be in global space
- Each class in a hierarchy may have its own flags
- The flags must be type specific

If having only one kind of flags is acceptable, a simple CRTP solution is:

template<class T> class CFlags
{
typedef typename T::flags_type flags_type;
public:
VOID AddFlag(flags_type eFlag);
VOID RemoveFlag(flags_type eFlag);
};

class CClass1 : public CFlags<CClass1>
{
public:
enum EFlags1
{
...
};
typedef EFlags1 flags_type;
};

class CClass2 : public CClass1,public CFlags<CClass2>
{
public:
enum EFlags2
{
...
};
typedef EFlags2 flags_type;
};


Michael
 
M

Michael DOUBEZ

Michael DOUBEZ a écrit :
Marco Nef a écrit :
Hi there,

I'm trying to do something like the following:

template<class TYPE> class CFlags
{
public:
VOID AddFlag(TYPE eFlag);
VOID RemoveFlag(TYPE eFlag);
};

class CClass1 : public CFlags<CClass1::EFlags>
{
public:
typedef enum EFlags
{
...
} EFlags;
};

class CClass2 : public CClass1,public CFlags<CClass2::EFlags>
{
public:
typedef enum EFlags
{
...
} EFlags;
};

I know that this cannot work because the EFlags are not known where
needed. I've tried many things, but none was a nice solution or worked
at all (I prefer a real C++ solution, which means there should be no
macros).

Does anyone have an idea how to solve the following problems in a nice
C++ way?

- EFlags should not be in global space
- Each class in a hierarchy may have its own flags
- The flags must be type specific

If having only one kind of flags is acceptable, a simple CRTP solution is:

[garbage]

sorry. Ignore that.

Michael
 
M

Michael DOUBEZ

Marco Nef a écrit :
Hi there,

I'm trying to do something like the following:

template<class TYPE> class CFlags
{
public:
VOID AddFlag(TYPE eFlag);
VOID RemoveFlag(TYPE eFlag);
};

class CClass1 : public CFlags<CClass1::EFlags>
{
public:
typedef enum EFlags
{
...
} EFlags;
};

class CClass2 : public CClass1,public CFlags<CClass2::EFlags>
{
public:
typedef enum EFlags
{
...
} EFlags;
};

I know that this cannot work because the EFlags are not known where needed.
I've tried many things, but none was a nice solution or worked at all (I
prefer a real C++ solution, which means there should be no macros).

Does anyone have an idea how to solve the following problems in a nice C++
way?

- EFlags should not be in global space
- Each class in a hierarchy may have its own flags
- The flags must be type specific

Since "EFlags should not be in global space", that means you cannot use
it directly in CFlags<> instance (i.e. in member or in function
parameters), only in called function. As a consequence, the derived
class must also handle the storage of the flags storage.

The closer solution I could think of is the following:
template<class T_CRTP> class CFlags
{
public:
template<TYPE>
void AddFlag(TYPE eFlag)
{
TYPE current;
static_cast<T_CRTP>(this)->get_flags(current);
//operations
static_cast<T_CRTP*>(this)->set_flags(current);
}
template<TYPE>
void RemoveFlag(TYPE eFlag)
{
TYPE current;
static_cast<T_CRTP*>(this)->get_flags(current);
//operations
static_cast<T_CRTP*>(this)->set_flags(current);
}
};

And

class CClass1 : public CFlags<CClass1>
{
public:
enum EFlags1
{
flagA
...
};
void get_flags(EFlags1& flags);
void set_flags(EFlags1& flags);

enum EFlags2
{
flagB
...
};
void get_flags(EFlags2& flags);
void set_flags(EFlags2& flags);
};


CClass1 c1:
//Calls CFlags<CClass1>::AddFlag<CClass1::EFlags1>(CClass1::EFlags1)
c1.AddFlag(CClass1::flagA);
//Calls CFlags<CClass1>::AddFlag<CClass1::EFlags2>(CClass1::EFlags2)
c1.AddFlag(CClass1::flagB);


Michael
 
M

Marco Nef

Michael DOUBEZ said:
Marco Nef a écrit :

Since "EFlags should not be in global space", that means you cannot use it
directly in CFlags<> instance (i.e. in member or in function parameters),
only in called function. As a consequence, the derived class must also
handle the storage of the flags storage.

The closer solution I could think of is the following:
template<class T_CRTP> class CFlags
{
public:
template<TYPE>
void AddFlag(TYPE eFlag)
{
TYPE current;
static_cast<T_CRTP>(this)->get_flags(current);
//operations
static_cast<T_CRTP*>(this)->set_flags(current);
}
template<TYPE>
void RemoveFlag(TYPE eFlag)
{
TYPE current;
static_cast<T_CRTP*>(this)->get_flags(current);
//operations
static_cast<T_CRTP*>(this)->set_flags(current);
}
};

And

class CClass1 : public CFlags<CClass1>
{
public:
enum EFlags1
{
flagA
...
};
void get_flags(EFlags1& flags);
void set_flags(EFlags1& flags);

enum EFlags2
{
flagB
...
};
void get_flags(EFlags2& flags);
void set_flags(EFlags2& flags);
};


CClass1 c1:
//Calls CFlags<CClass1>::AddFlag<CClass1::EFlags1>(CClass1::EFlags1)
c1.AddFlag(CClass1::flagA);
//Calls CFlags<CClass1>::AddFlag<CClass1::EFlags2>(CClass1::EFlags2)
c1.AddFlag(CClass1::flagB);


Michael

Thanks for your idea. But the problem is that there are tons of classes that
should be derived from CFlags. So it is no option to implement the storage
on each of them.

At the moment we do have a base class that is not type specific. But the
problem are collisions of flags in the hierarchy.

- Marco
 
I

IsaakBegProg

Hi there,

I'm trying to do something like the following:

template<class TYPE> class CFlags
{

What about ...


template <class _Chk>
class AssertStatA;
template <class _Chk>
class AssertStatB;

template < template<class> class __Assert >
class _FlgController
{
protected:
template <class _Flag> void Add(_Flag _data){
__Assert<_Flag>();
cout << (int)_data << endl;
}
template <class _Flag> void Rem(_Flag _data){
__Assert<_Flag>();
cout << (int)_data << endl;
}
};

class A : public _FlgController<AssertStatA>
{
public:
typedef enum EFlag
{
E_FLAG_A = 0
};
public:
using _FlgController<AssertStatA>::Add;
using _FlgController<AssertStatA>::Rem;
};

template<> class AssertStatA<A::EFlag>{};

class B : public A, public _FlgController<AssertStatB>
{
public:
typedef enum EFlag
{
E_FLAG_B = 1
};
public:
using _FlgController<AssertStatB>::Add;
using _FlgController<AssertStatB>::Rem;
};
template<> class AssertStatB<B::EFlag>{};


for example:
A a;
B b;

a.Add(A::E_FLAG_A);
// a.Add(B::E_FLAG_B); //static assert
((A&)b).Add(A::E_FLAG_A);
b.Add(B::E_FLAG_B);
 
P

Pete Becker

I know that this cannot work because the EFlags are not known where needed.
I've tried many things, but none was a nice solution or worked at all (I
prefer a real C++ solution, which means there should be no macros).

Last time I looked, macros were part of C++. If the goal is to add
those two members to the class, they provide a sound solution. Fancy
template tricks might work, but the time spent getting them to work
could be far better spent doing other things.
 
G

Grizlyk

You can try to replace inheritance of implementation by composition:

template<class T>
class CFlags
{
public:
void AddFlag(T::flags_type eFlag);
void RemoveFlag(T::flags_type eFlag);
};

class CClass1
{
public:
enum flags_type { a };

CFlags<CClass1> flags;
};

class CClass2: public CClass1
{
public:
enum flags_type { b };

CFlags<CClass2> flags;
};

void foo()
{
CClass2 tmp;

tmp.CClass1::flags.AddFlag( CClass1::a );
tmp.flags.AddFlag( CClass2::b );
}

Maksim A. Polyanin
http://grizlyk1.narod.ru/cpp_new
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top