Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > const/non const member function vs. templates

Reply
Thread Tools

const/non const member function vs. templates

 
 
Markus Keppeler
Guest
Posts: n/a
 
      07-26-2011
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?

any help is appreciated,
Markus

--
Nur tote Fische schwimmen mit dem Strom.
 
Reply With Quote
 
 
 
 
Virchanza
Guest
Posts: n/a
 
      07-26-2011
On Jul 26, 1:58*pm, Markus Keppeler <(E-Mail Removed)> wrote:

> class XY
> {
> * *Dummy *pGetMe( * * * * * *(returns pointer to some
> * *); * * * * * * * * * * * *dummy member orwhatever)
>
> * *const Dummy *pGetMe( * * *(returns const pointer to some
> * *) const; * * * * * * * * *dummy member or whatever).
>
> }
>



Just one way of going about this:

Dummy const *pGetMe() const
{
return address_of_member_data; // or whatever else it does
}

Dummy *pGetMe()
{
return const_cast<Dummy*>( const_cast<XY const *>(this)-
>pGetMe() );

}
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      07-26-2011
On 7/26/2011 9:12 AM, Virchanza wrote:
> On Jul 26, 1:58 pm, Markus Keppeler<(E-Mail Removed)> wrote:
>
>> class XY
>> {
>> Dummy *pGetMe( (returns pointer to some
>> ); dummy member orwhatever)
>>
>> const Dummy *pGetMe( (returns const pointer to some
>> ) const; dummy member or whatever).
>>
>> }
>>

>
>
> Just one way of going about this:
>
> Dummy const *pGetMe() const
> {
> return address_of_member_data; // or whatever else it does
> }
>
> Dummy *pGetMe()
> {
> return const_cast<Dummy*>( const_cast<XY const *>(this)-
>> pGetMe() );

> }


Actually, I'd consider implementing them in reverse. Think about it.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
Markus Keppeler
Guest
Posts: n/a
 
      07-26-2011
First of all: Thanks for the reply .

Am 26.07.2011 15:12, schrieb Virchanza:
> Just one way of going about this:
>
> [...]
> return const_cast<Dummy*>( const_cast<XY const *>(this)->>pGetMe() );


I agree that a const_cast might be a solution here. But the example
was only a very small and trivial one, I'm dealing with more complex
ones where a const_cast needs more explizit work to be done additionally.

Secondly, I don't like const_cast at all, but that is only my personal
flavor .

Thats why I was curious about any template mechanism that might solve
this more elegant (though I doubt that such one exists ).

thx,
Markus

--
Nur tote Fische schwimmen mit dem Strom.
 
Reply With Quote
 
Balog Pal
Guest
Posts: n/a
 
      07-26-2011

"Markus Keppeler" <(E-Mail Removed)> az alábbiakat írta a következo
hírüzenetben: 4e2ecb09$0$6639$(E-Mail Removed)-online.net...
> First of all: Thanks for the reply .
>
> Am 26.07.2011 15:12, schrieb Virchanza:
>> Just one way of going about this:
>>
>> [...]
>> return const_cast<Dummy*>( const_cast<XY const *>(this)->>pGetMe() );

>
> I agree that a const_cast might be a solution here. But the example was
> only a very small and trivial one, I'm dealing with more complex ones
> where a const_cast needs more explizit work to be done additionally.


This hardy makes sense. The complexity of the work is irrelevant. With the
above solution you will have it once, and the other function delegates to
the single solution. You have a choice on direction, the baseline is to have
the implementation in const and call that from non-const. With the other way
you open the danger to change state in a const object.

> Secondly, I don't like const_cast at all, but that is only my personal
> flavor .
>
> Thats why I was curious about any template mechanism that might solve this
> more elegant (though I doubt that such one exists ).


You can have the two members and make them call a single implementation in a
template function. That can be a private static in the class. IMO that
solution is less elegant by far.

 
Reply With Quote
 
Werner
Guest
Posts: n/a
 
      07-26-2011
On Jul 26, 2:58*pm, Markus Keppeler <(E-Mail Removed)> 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.


Implement the const one in terms of the non-const one:

Rationale:
- Conversion to more const is automatic and is natural.

Note:
- Only perform the cast if <this> is not modified during the
applicable function.

E.g:

struct XY
{
struct Dummy
{
Dummy( int n ): n_( n ){}
int n_;
};
Dummy d_;

XY(): d_( 10 ){}

Dummy *pGetMe()
{
return &d_;
}

const Dummy *pGetMe() const
{
return const_cast<XY*>(this)->pGetMe();
}
};


int main()
{
const XY cxy;
XY xy;

XY:ummy* d1 = xy.pGetMe();
const XY:ummy* d2 = cxy.pGetMe();
std::cout << "--- The end ---" << std::endl;
}


 
Reply With Quote
 
Werner
Guest
Posts: n/a
 
      07-26-2011
> On Jul 26, 2:58*pm, Markus Keppeler <(E-Mail Removed)> wrote:
> --
> Nur tote Fische schwimmen mit dem Strom.


Net 'n onnosel mens swem teen die stroom, veral
in die see, en dit lei meestal tot verdrinking ...
.... 'n mens is duidelik nie 'n vis nie.


 
Reply With Quote
 
Virchanza
Guest
Posts: n/a
 
      07-26-2011
On Jul 26, 3:04*pm, Victor Bazarov <(E-Mail Removed)> wrote:

> > Dummy const *pGetMe() const
> > {
> > * * *return address_of_member_data; *// or whatever else it does
> > }

>
> > Dummy *pGetMe()
> > {
> > * * *return const_cast<Dummy*>( const_cast<XY const *>(this)-
> >> pGetMe() );

> > }

>
> Actually, I'd consider implementing them in reverse. *Think about it.



Assuming that both functions perform the *exact* same
functionality, (the only difference being that the non-const version
returns a non-const pointer/reference), I like the idea of making the
non-const version call the const version because then you can use the
compiler to make sure that the shared body of code for the two
functions doesn't alter any read-only member variables. What I mean is
that the following problematic code would not compile if the non-const
version called the const version:

Dummy *pGetMe()
{
member_variable += 5;
return &member_variable;
}

Dummy const *pGetMe() const
{
return const_cast<XY*>(this)->pGetMe();
}

 
Reply With Quote
 
Markus Keppeler
Guest
Posts: n/a
 
      07-27-2011
Hi!

Am 26.07.2011 17:03, schrieb Balog Pal:
>> I agree that a const_cast might be a solution here. But the example was
>> only a very small and trivial one, I'm dealing with more complex ones
>> where a const_cast needs more explizit work to be done additionally.

>
> This hardy makes sense. The complexity of the work is irrelevant. With the
> above solution you will have it once, and the other function delegates to
> the single solution. You have a choice on direction, the baseline is to have
> the implementation in const and call that from non-const. With the other way
> you open the danger to change state in a const object.


I agree that the other way (calling non-const from const) is quite
dangerous if the non-const changes later on.

My problem here with the const_cast comes from the legacy. We have a
difference in the const/non const functions for example in the way the
the non const functions touch our internal "undo" system, whereas the
const function doesn't need to.

So for each const_cast I'd have to make sure to keep the undo up to
date. This will introduce more noise than a double const/non const
version that is reasonably short.

thx,
Markus

--
Nur tote Fische schwimmen mit dem Strom.
 
Reply With Quote
 
Balog Pal
Guest
Posts: n/a
 
      07-27-2011
"Markus Keppeler" <(E-Mail Removed)>

> My problem here with the const_cast comes from the legacy. We have a
> difference in the const/non const functions for example in the way the the
> non const functions touch our internal "undo" system, whereas the const
> function doesn't need to.


This doesn't map back to the original question.

If you have a genuine difference in implementations of the two functions,
then you are out of options. You can't meld them with either delegation or
templates.

> So for each const_cast I'd have to make sure to keep the undo up to date.


That sounds like the wrong association. The undo buffer shall be tied to
mutation itself, not constness on a pointer or reference. Why not deal with
the undo in members of the returned thing?

Also you suggest *diffenent* semantics of the functions with that additional
task. So they are no longer good for overload!

In my practice I soon dropped const overloads, and have the two functions
with different names. (Mostly a W attached at end of non-const version.) So
the user who has intention for modification will explicitly ask that
version. Standing out in the code well. Signaling an error when the
incorrect version used. And dodging the very common case where you don't
have intention tomodify in a particular operation, but have a mutable (for
other purposes) object around, and have the non-intended operation selected.

> This will introduce more noise than a double const/non const version that
> is reasonably short.


Again, the content of the implementation is an orthogonal issue.

I suggest to stick to the 'say what you mean, mean what you say' principle.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
const correctness - should C++ prefer const member over non-const? fungus C++ 13 10-31-2008 05:33 AM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
how to Specializations of function Templates or Overloading Function templates with Templates ? recover C++ 2 07-25-2006 02:55 AM
Overriding const member function with non-const David Scarlett C++ 3 02-07-2006 01:34 PM
Templates templates templates JKop C++ 3 07-21-2004 11:44 AM



Advertisments