473,756 Members | 1,810 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

const_cast<...> (this)

class my_class {
public:
my_class() : value(0) { }
int& get_value() { return value; }

const int& get_value() const {
my_class& c = const_cast<my_c lass&>(*this);
return c.get_value();
}

private:
int value;
};

int main() {
const my_class c;
return c.get_value();
}

Does the above cause undefined behavior?

Thanks

Oct 15 '06 #1
11 5034
* Squeamizh:
class my_class {
public:
my_class() : value(0) { }
int& get_value() { return value; }

const int& get_value() const {
my_class& c = const_cast<my_c lass&>(*this);
return c.get_value();
}

private:
int value;
};

int main() {
const my_class c;
return c.get_value();
}

Does the above cause undefined behavior?
No, but (1) it would if you tried to modify the object, because it's
originally declared 'const', and (2) instead of the monstrosity above,
where you expose a data member completely via absurd code, you could and
probably should simply do

struct MyClass
{
int value;
MyClass(): value( 0 ) {}
};

If you absolutely want to use a Java-like "getter" (it has a purpose in
Java, namely to support component usage via instrospection) then I
suggest you change the name 'get_value' to simply 'value'.

You don't write

get_sin(0.5)*ge t_cos(0.5)

do you?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 15 '06 #2
Alf P. Steinbach wrote:
[const_cast<...> (this)]
Does the above cause undefined behavior?

No, but (1) it would if you tried to modify the object, because it's
originally declared 'const', and (2) instead of the monstrosity above,
where you expose a data member completely via absurd code, you could and
probably should simply do

[struct]
I agree. The code I posted was simplified in order to clearly express
the root of my concern. Since you brought it up, though, I'd be
grateful to hear if you think I am using the wrong solution for my
problem. I originally had a class declaration that looks like this:

class my_class {
public:
virtual int& get_value() = 0;
virtual const int& get_value() const = 0;
};

my_class does not actually contain an "int value" (hence the pure
virtual getter) because I would like to have a descendant of my_class
("class outer") that contains another descendant of my_class ("class
inner"). inner contains the actual "int value", and outer just
delegates the above two functions to inner. However, I don't want
outer to have to override both a non-const version of get_value and a
const version of get_value. I would like to avoid the tediousness of
overriding twice as many getters in all these classes.

This may still seem absurd, but it is still a bit simplified. There
are actually eight or so getters like the above, and several different
"outer" and "inner" classes that all inherit my_class.
If you absolutely want to use a Java-like "getter" (it has a purpose in
Java, namely to support component usage via instrospection) then I
suggest you change the name 'get_value' to simply 'value'.

You don't write

get_sin(0.5)*ge t_cos(0.5)

do you?
Again, I agree. I often have difficulty reading the snippets that
others post, and I thought the addition of "get" would make it easier
to read my example.

Oct 15 '06 #3
Alf P. Steinbach wrote:
* Squeamizh:
>class my_class {
public:
my_class() : value(0) { }
int& get_value() { return value; }

const int& get_value() const {
my_class& c = const_cast<my_c lass&>(*this);
return c.get_value();
}

private:
int value;
};

int main() {
const my_class c;
return c.get_value();
}

Does the above cause undefined behavior?

No, but (1) it would if you tried to modify the object, because it's
originally declared 'const',
The compiler would bark at the attempt:

const int& get_value() const {
my_class& c = const_cast<my_c lass&>(*this);
return c.get_value();
}

As you can see, the const version of get_value returns a const int &.
and (2) instead of the monstrosity above,
where you expose a data member completely via absurd code, you could and
probably should simply do

struct MyClass
{
int value;
MyClass(): value( 0 ) {}
};

If you absolutely want to use a Java-like "getter" (it has a purpose in
Java, namely to support component usage via instrospection) then I
suggest you change the name 'get_value' to simply 'value'.

You don't write

get_sin(0.5)*ge t_cos(0.5)

do you?
I think the OP is not really interested in the particular example. Instead,
I think the code is an attempt at avoiding code-duplication. A more natural
example would be a smart-pointer where you have

T* operator* ( void );

and

T const * operator* ( void ) const;

and both functions usually have the same body. I am not sure what to think
of the const_cast<appr oach, though. It seems that unless it is an
established idiom within your peer group, you would have to put in a
comment saying that you checked the standard and that this use of
const_cast<is benign---hardly better than just duplicating the code of a
one-line function body.
Best

Kai-Uwe Bux
Oct 15 '06 #4
* Squeamizh:
Alf P. Steinbach wrote:
>>[const_cast<...> (this)]
Does the above cause undefined behavior?
No, but (1) it would if you tried to modify the object, because it's
originally declared 'const', and (2) instead of the monstrosity above,
where you expose a data member completely via absurd code, you could and
probably should simply do

[struct]

I agree. The code I posted was simplified in order to clearly express
the root of my concern. Since you brought it up, though, I'd be
grateful to hear if you think I am using the wrong solution for my
problem. I originally had a class declaration that looks like this:

class my_class {
public:
virtual int& get_value() = 0;
virtual const int& get_value() const = 0;
};

my_class does not actually contain an "int value" (hence the pure
virtual getter) because I would like to have a descendant of my_class
("class outer") that contains another descendant of my_class ("class
inner"). inner contains the actual "int value", and outer just
delegates the above two functions to inner.
Ah, design issue. First off, this is a separate issue from the const
overloading issue. This issue is about one class, here 'my_class',
requiring that some other class, here 'inner', provides a member of a
given type (because of the references).

I.e., that one class dictates the /implementation/ of another class.

That's generally UnGood.

At the very least, try to separate implementation from interface, by

class MyClass
{
public:
virtual int value() const = 0;
virtual void setValue( int v ) = 0;
};

But note that this interface is essentially an interface to a /global
variable/ -- where I'm using the term "global" very loosely, but the
point is that the value can be modified from anywhere, and in the end
someone will have to resort to painful debugging and searching of tons
of code to establish where the heck the final useful value comes from,
or where the code is that puts in a very much less than useful value...

The problem is the public setter function.

The solution depends strongly on what the actual design is all about,
but generally, most designs where the client code changes values (this
makes it all but impossible to maintain any class invariants) can be
recast as more reasonable designs where the client code just states the
effects or results wanted -- operations, not raw data.
[moved this paragraph up here from further down in the text]
This may still seem absurd, but it is still a bit simplified. There
are actually eight or so getters like the above, and several different
"outer" and "inner" classes that all inherit my_class.
Ouch. Those eight or so values seem to be strongly related, and if they
aren't, they should be, to appear in the same interface. Why not pack
them in a class and provide just /one/ set-and-get pair, or better yet,
as mentioned above, a single getter function 'T const& value() const',
or even better better yet, as mentioned above, operations, not raw data?

OK, I know one reason: an unreasonable psychotic project lead who
absolutely don't want any such "fancy" stuff, it /must/ be spaghetti,
visually identical in texture (yes) to the rest of the code.

But apart from that?

However, I don't want
outer to have to override both a non-const version of get_value and a
const version of get_value. I would like to avoid the tediousness of
overriding twice as many getters in all these classes.
Note: at least for primitive types such as 'int' those aren't really
getters, they're setters camouflaged as getters, because they return
references.

But when you have a getter where the constness of the result should
depend on the constness of *this, and the logic of that getter is
complex, deferring to a common implementation and using const_cast is
all right (the common implementation can be templatized in order to
avoid the cast, but that's very seldom worth the coding investment).
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 15 '06 #5
* Kai-Uwe Bux:
Alf P. Steinbach wrote:
>* Squeamizh:
>>class my_class {
public:
my_class() : value(0) { }
int& get_value() { return value; }

const int& get_value() const {
my_class& c = const_cast<my_c lass&>(*this);
return c.get_value();
}

private:
int value;
};

int main() {
const my_class c;
return c.get_value();
}

Does the above cause undefined behavior?
No, but (1) it would if you tried to modify the object, because it's
originally declared 'const',

The compiler would bark at the attempt:

const int& get_value() const {
my_class& c = const_cast<my_c lass&>(*this);
return c.get_value();
}

As you can see, the const version of get_value returns a const int &.
Consider e.g.

int const& value() const
{
MyClass& c = const_cast<my_c lass&>(*this);
int& refValue = c.value();

if( refValue == 0 ) { refValue = 666; }
return refValue;
}

Another problem, that I've mentioned elsethread, is that 'int const&' as
opposed to just 'int' forces a given implementation, /and/ may be less
efficient...

And a third problem, also mentioned elsethread, is that the non-const
"getter" function is in reality a setter function.

Rest snipped - agreed.

Cheers,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 15 '06 #6
S S

Squeamizh wrote:
class my_class {
public:
my_class() : value(0) { }
int& get_value() { return value; }

const int& get_value() const {
my_class& c = const_cast<my_c lass&>(*this);
return c.get_value();
}

private:
int value;
};

int main() {
const my_class c;
return c.get_value();
}

Does the above cause undefined behavior?
You are not returning const int& as you have modified it. That is
wrong.
The purpose of calling const function is defied here. If you are
calling const function, you must have const obj in first place and then
inside it you are not supposed to modify it. The better way to do it
reverse. Call const version of function from non const one.

int& get_value()
{
return const_cast<int& >(static_cast<c onst myclass&)(*this ));
//Here I am casting away constness in return type and adding const to
*this's type. This will call non const version of function.
}
This will aviod code duplication as well as work fine.
Thanks
Oct 15 '06 #7
S S

S S wrote:
Squeamizh wrote:
class my_class {
public:
my_class() : value(0) { }
int& get_value() { return value; }

const int& get_value() const {
my_class& c = const_cast<my_c lass&>(*this);
return c.get_value();
}

private:
int value;
};

int main() {
const my_class c;
return c.get_value();
}

Does the above cause undefined behavior?
You are not returning const int& as you have modified it. That is
wrong.
The purpose of calling const function is defied here. If you are
calling const function, you must have const obj in first place and then
inside it you are not supposed to modify it. The better way to do it
reverse. Call const version of function from non const one.

int& get_value()
{
a correction
return const_cast<int& >(static_cast<c onst myclass&)(*this ).get_value());
//Here I am casting away constness in return type and adding const to
*this's type. This will call non const version of function.
}
This will aviod code duplication as well as work fine.
Thanks
Oct 15 '06 #8
Squeamizh wrote:
class my_class {
public:
my_class() : value(0) { }
int& get_value() { return value; }

const int& get_value() const {
my_class& c = const_cast<my_c lass&>(*this);
return c.get_value();
}

private:
int value;
};

int main() {
const my_class c;
return c.get_value();
}

Does the above cause undefined behavior?
Not yet, but you probably want to read up on mutable.

HTH,
Michiel Salters

Oct 17 '06 #9

Squeamizh wrote:
class my_class {
public:
my_class() : value(0) { }
int& get_value() { return value; }

const int& get_value() const {
my_class& c = const_cast<my_c lass&>(*this);
return c.get_value();
}

private:
int value;
};
It makes more sense to go the other way; make the non-const version
call the const version. Of course, the assumption is that you are
returning the same value but possibly doing something on the side when
not const. Chances are your in poor design mode but whatever...make
the non-const version call the const version. Then you can't run into
UB.
Does the above cause undefined behavior?
No, but your getting close to causing UB. The above code also has
pointless functions...you don't need the non-const version at all.

Oct 17 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
4307
by: R. Anbeeswaran | last post by:
Hi All, void main() { const int i = 20; int *p = const_cast<int*>(&i); *p = 40; cout <<"i="<< i <<"\t"<<"*p="<<*p<<"\n"; }
2
1690
by: Derek | last post by:
Something puzzles me about Boost's shared_ptr implementation: template <typename T> class shared_ptr { public: T* operator->() const { return p; }
11
5151
by: Scott Brady Drummonds | last post by:
Hi, everyone, I've checked a couple of on-line resources and am unable to determine how reinterpret_cast<> is different from static_cast<>. They both seem to perform a compile-time casting of one type to another. However, I'm certain that there is something else that is happening. Can someone explain the difference or recommend an online site that can explain it to me?
3
2078
by: Siemel Naran | last post by:
Here is a question about implicit conversion from T (&) to ptrcarray<T>. I wrote a class template <class T> struct ptrcarray { T * array; size_t size;
24
17489
by: Marcus Kwok | last post by:
Hello, I am working on cleaning up some code that I inherited and was wondering if there is anything wrong with my function. I am fairly proficient in standard C++ but I am pretty new to the .NET managed C++. It seems to work fine, but everyone knows that programs with errors can still appear to "work fine" :) I am working with VS .NET 2003; I am unable to upgrade to 2005 at this time, so I cannot use the newer syntax or features. ...
5
9200
by: Tom Smith | last post by:
I hardly dare ask this given the furore in another thread over strings and const... My problem is this. I am assured that casting away the constness of the return value of std::string::c_str() is an Error according to the Standard. But I need to pass it to a function (in an old and unpleasant C library, ugh) which takes an ordinary char*. What should I do? Is it really necessary to make a fresh copy of the string? (I'm not asking this...
3
4087
by: ryan.gilfether | last post by:
I have a problem that I have been fighting for a while and haven't found a good solution for. Forgive me, but my C++ is really rusty. I have a custom config file class: class ConfigFileValue { public: operator string(); // allow this class to be typecast into a string operator char*(); // allow this class to be typecast into a char*
10
3787
by: Alex Vinokur | last post by:
Hi, Is it possible to do C++-casting from const pair<const unsigned char*, size_t>* to const pair<unsigned char*, size_t>* ? Alex Vinokur
0
9431
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10014
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9689
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8688
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7226
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5119
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5289
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3780
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2647
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.