Re: const/non const member function vs. templates
On 26 Jul., Markus Keppeler wrote:
Hi Together!
In some (partly legacy) code I have member functions like this:
// class Dummy (class of any type).
class XY
{
Dummy *pGetMe( (returns pointer to some
); dummy member orwhatever)
const Dummy *pGetMe( (returns const pointer to some
) const; dummy member or whatever).
}
Since the implementations on both pGetMe's are 100% identically, only
that they use const/non const types/functions, I'd like to merge them.
I cannot implement the non-const version by calling down to the const
one, since at some level it needs to fetch the non-const pointer to
something. Here also some legacy-issues come into, so I cannot
refactor the entire design ;-).
My next thought was to use templates, like
template <class T>
T pGetMe();
, but here I don't know how to deal with the const/non constness of
the member function. Can I add the const/non const based on the type
of T?
The following template should do what you want, but the syntax is a
bit different: You'd have to declare a public member Me and take the
address of it:
class XY
{
public:
ConstCorrectAccessor<Dummy> Me;
};
void foo (const XY& xy)
{
const Dummy* OK = &xy.Me;
Dummy* DOES_NOT_COMPILE = &xy.Me;
}
--------------------------------------------------------------------------------------------------------------------------------------------
// Wrapper for plain pointers that behaves as const-correct
// accessor.
template<class t_Class>
class ConstCorrectAccessor
{
t_Class* m_InternalPointer;
public:
ConstCorrectAccessor (t_Class* Pointer)
: m_InternalPointer (Pointer)
{}
// Accessor methods with const-correct overload.
const t_Class* operator-> () const {return m_InternalPointer;}
t_Class* operator ->() {return m_InternalPointer;}
const t_Class* operator& () const {return m_InternalPointer;}
t_Class* operator& () {return m_InternalPointer;}
};
class SomeClass
{
public:
void foo () const {}
void bar () {}
};
class AnotherClass
{
public:
ConstCorrectAccessor<SomeClass> ConstCorrectAccess;
SomeClass* PlainPointerAccess;
public:
AnotherClass (SomeClass* Object)
: PlainPointerAccess (Object),
ConstCorrectAccess (Object)
{}
void test () const
{
ConstCorrectAccess->foo (); // OK
//ConstCorrectAccess->bar (); // Error: Non-const method on
SomeObject.
PlainPointerAccess->foo (); // OK
PlainPointerAccess->bar (); // BAD: Const-correctness not
propagated.
}
};
int main ()
{
SomeClass a;
const AnotherClass b (&a);
b.ConstCorrectAccess->foo (); // OK
// b.ConstCorrectAccess->bar (); // Compilation error: b is const
b.PlainPointerAccess->foo (); // OK
b.PlainPointerAccess->bar (); // BAD: Const-correctness is not
propagated
AnotherClass c (&a);
c.ConstCorrectAccess->foo (); // OK
c.ConstCorrectAccess->bar (); // OK: c is not const
c.PlainPointerAccess->foo (); // OK
c.PlainPointerAccess->bar (); // OK: c is not const
const SomeClass* constpointer2SomeClass = &b.ConstCorrectAccess;
const SomeClass* constpointer2SomeClass2 = &c.ConstCorrectAccess;
// SomeClass* pointer2SomeClass = &b.ConstCorrectAccess; //
Compilation error: b is const
SomeClass* pointer2SomeClass2 = &c.ConstCorrectAccess;
return 0;
}
Regards,
Stuart