Correct usage(s) of const_cast<> - c++

As a common rule, it is very often considered a bad practice to use const_cast<>() in C++ code as it reveals (most of the time) a flaw in the design.
While I totally agree with this, I however wonder what are the cases were using const_cast<>() is ok and the only solution.
Could you guys please give me some examples you know/you encountered ?
Thank you very much.

it is pretty much designed to be only used with legacy APIs that are not const correct i.e. with a function you can't change that has non const interface but doesn't actually mutate anything on the interface

Like others have said, its primary purpose is to remove const from objects in order to pass to non-const correct functions you know won't modify the argument.
There is a trick (by Meyers?) to avoid code duplication, and it goes like this:
struct foo
{
const return_type& get(void) const
{
// fancy pants code that you definitely
// don't want to repeat
return theValue; // and got it
}
return_type& get(void)
{
// well-defined: Add const to *this,
// call the const version, then
// const-cast to remove const (because
// *this is non-const, this is ok)
return const_cast<return_type&>(static_cast<const foo&>(*this).get());
}
};

const_cast is also used to remove volatile modifiers, as put into practice in this (controversed) article:
http://www.drdobbs.com/184403766

I agree with your statement that its normal use is because you need to hide a 'design flaw'.
IME one of the typical usage scenarios is when you try to interface C++ to existing C code. A lot of existing C code takes C strings as char * even when the string is not modified whereas they're usually represented as something that converts to a const char * in C++. That's an impedance mismatch between the two languages that you would normally solve by using a const_cast. Of course you'd better be very sure that the code you're interfacing with doesn't get any cute ideas about modifying the data that's being passed in.
I would say that it's a code smells in newly written code, but for interfacing with older C and C++ code, it's an necessary evil. That said, I would be extremely wary of code that requires const_cast for any non-POD objects as that is normally a problem that should be solved at the design level and not the code level.

One legitimate use (in my opinion) is with std::set iterators. They are always const, in order to prevent changing the key used in the set. Changing the key would break the internal structure of the set and cause undefined behavior.
However, as long as the key doesn't change it's safe to change other data in the object.
Let's say you have an std::set like this:
std::set<MyObject> some_set;
And a class like this:
class MyObject {
public:
MyObject(const std::string &key)
: key_(key) {}
bool operator<(const MyObject &other) const {
return key_ < other.key_;
}
private:
// ...
// <some other data>
// ...
const std::string key_;
};
In the above example, the key is already const, so even if you modify the object, you cannot break the internal structure of the set.
Normally you can only get a const reference out of a set iterator:
const MyObject &object = *some_set_iterator;
But since the key is const, it's safe to const_cast the dereferenced iterator:
MyObject &object = const_cast<MyObject &>(*some_set_iterator);

One very legitimate use of this is when you have both a const and non const api (for const and non const objects respectively) as in
class Bar {
const SomeType& foo() const;
SomeType& foo();
}
Then since we don't want to duplicate the code in both functions we often use
class Bar {
SomeType& foo() {
//Actual implementation
}
const SomeType& foo() const {
return const_cast<Bar*>(this)->foo();
}
};
This is of course assuming that foo does not do something that violates the const semantics.

Yes of course, when your calling code that you can't modify and isn't const correct. It should be noted that you should only use it with calls to functions that you know for certain won't modify your data!

There is an example of const_cast usage in c++ primer(5th edition) book.
Below function returns reference to const string
// return a reference to the shorter of two strings
const string &shorterString(const string &s1, const string
&s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
The book then mentions the case when we want a non const reference.
We can call the function on a pair of nonconst string arguments, but
we’ll get a reference to a const string as the result. We might want
to have a version of shorterString that, when given nonconst
arguments, would yield a plain reference. We can write this version of
our function using a const_cast:
string &shorterString(string &s1, string &s2)
{
auto &r = shorterString(const_cast<const string&>(s1),
const_cast<const string&>(s2));
return const_cast<string&>(r);
}
This version calls the const version of shorterString by casting its
arguments to references to const. That function returns a reference to
a const string, which we know is bound to one of our original,
nonconst arguments. Therefore, we know it is safe to cast that string
back to a plain string& in the return.
According to the book, it should be used if we know it is safe to cast.

Related

Should methods returning const std::string& return const std::string_view instead?

Assume we have a simple getter method in a class that returns a const reference to a std::string member:
const std::string& getString() const noexcept { return someString; }
With the advent of std::string_view in C++17, I wonder whether it has any advantages of writing this instead:
const std::string_view getString() const noexcept { return someString; }
Does one method have advantages/disadvantages over the other? Clearly (correct me if I'm wrong) both solutions will definitely be better than this:
const char* getString() const noexcept { return someString.c_str(); }
I've seen this related question, but I'm asking for something slightly different.
Yes, you should write:
const std::string& getString() const noexcept { return someString; }
Instead of (note: not const, because never return const values):
std::string_view getString() const noexcept { return someString; }
The reason is - you already have a string. So it's not like you have to pay anything extra to get a string out of it. And string has one notable semantic difference to an arbitrary string_view: it's null-terminated by guarantee. We know this. Maybe some downstream user needs to rely on that information. If they need null-termination (e.g. they need to pass to some C API that requires it) and you give a string_view, they have to make a string out of it themselves. You save nothing, but potentially make downstream users do more work.
If, however, you had a vector<char> instead... then I would suggest to return a span<char const> or the equivalent thereof. Since there is no semantic difference and you're just providing a view.
There also the separate argument of what:
auto x = obj.getString();
should do. This either takes a copy of the string (expensive, but safe) or effectively a reference to it (cheap, but potentially dangling). But it doesn't entirely look like a reference, it looks like a value. This is a broad issue with reference-semantic types in general (things like reference_wrapper, string_view, span, tuple<T&...>, optional<T&> if it existed, etc.).
I don't have an answer for this case, but it's something to be aware of.

How to write a getter method so that it returns an rvalue

If we have this class definition
class BusDetails
{
private:
string m_busName;
public:
string BusName() const { return m_busName; }
};
how could the getter method be changed or used, so that using the return value as an lvalue would give a compiler error?
For example, if I use it like
int main(void)
{
BusDetails bus;
bus.BusName() = "abc"; // <--- This should give a compiler error
cout << bus.BusName() << endl;
return 0;
}
I get no compiler error, so apparently the assignment works, but the result is not as expected.
Update: this behavior is as expected with build-in types (i.e. the compiler gives an error at the above line of code if I have an int as a return type instead of string).
The BusName() was declared as a const function. So it can't change members.
Your function should return string& and not be const.
string& BusName() { return m_busName; }
In addition you can add for const object (this is const):
const string& BusName() const { return m_busName; }
It's not clear what behavior you want.
If you want the assignment to be an error, and keep all of the
flexibility of value return (e.g. you can modify the code to
return a calculated value), you can return std::string const.
(This will inhibit move semantics, but that's generally not
a big issue.)
If you want to be able to modify the "member", but still want
to retain flexibility with regards to how it is implemented in
the class, then you should provide a setter method. One
convention (not the only one) is to provide a getter function
like you have now (but returning std::string const), and
provide a function with the same name void
BusName( std::string const& newValue ) to set the value.
(Other conventions would use a name like SetBusName, or return
the old value, so client code could save and restore it, or
return *this, so client code could chain the operations:
obj.BusName( "toto" ).SomethingElse( /*...*/ ).
You may also provide a non-const member returning a reference
to a non-const. If you do this, however, you might as well make
the data member public.
Finally, you might provide a non-const member which returns
some sort of proxy class, so that assigning to it would in fact
call a setter function, and converting it to std::string would
call the getter. This is by far the most flexible, if you
want to support modifications by the client, but it's also by
far the most complex, so you might not want to use it unless you
need to.
Well it is kind of expected behavior what you have written.
You do return a copy of m_busName. Because you do not return the reference. Therefore a temporary copy of the return variable is made, and then the assignment takes place. operator= is "abc" called on that copy.
So the way to go would be string& BusName() const { return m_busName; }. But that shall give a compiler error.
You kind of want contradictory things. You say string BusName() const, yet you want to return a reference that will allow the state of the object to be changed.
However if you don't promise the object will not change you can drop the const and go with
string& BusName() { return m_busName; };
Or if you want to keep the const
const string& BusName() const { return m_busName; };
however this should give an error on the assignment, naturally.
The same goes for functions. If you do pass argument by reference it is a reference. If you see that you modify a copy, you must have not passed it by reference but by value.
The function does return an rvalue.
The problem is that std::string::operator= works with an rvalue on the left. Prior to C++11 it was difficult or impossible to prevent it from working: in C++11 they added (relatively late) what is colloquially known as rvalue references to this: the ability to overload methods and in-class operators based on the rvalue state of the object.
However, std::string was not modified, probably do to a mixture of not much time and dislike of breaking existing code without good reason.
You could patch around this problem a few ways. You could write your own string class that obeys rvalue reference to this. You could descend from std::string and block the operator= specifically. You could write an accessor object that has-a std::string that can cast-to std::string&& a d std::string& (based on rvalue status of this) implicitly, but blocks assignment with deleted method.
All three have issues. The last has the fewest issues, the second the most hidden pitfalls, the first is just drudgery.

Return std::string as const reference

I have a doubt on returning std::string as const reference.
class sample
{
public:
std::string mString;
void Set(const std::string& s)
{
mString = s;
}
std::string Get()
{
return mString;
}
};
In the Set function I am passing the std::string as const reference, const because its value is not changing inside the function.
And In Get function, actually I am confused here. Return std::string as value makes more sense. But I am not sure that, by passing the string as const reference makes any advantages. By returing string as reference will increase the exectuion speed, I think So, but I am not sure. But returning it as 'const makes any benefit for this?
The problem of deciding how to return a non-trivial object from some sort of a container is actually non-trivial:
If the class from which you return your value imposes any sort of constraint on the object, you can't return a non-const reference because it would loose the possibility to enforce its invariants. Clearly, returning an object by non-const reference is only viable if object the member function is called on is also non-const.
Exposing a const reference to an object would avoid the problem with the invariants but still implies that an object of the corresponding type is actually kept internally as an implementation detail.
Returning an object by value may incur a significant cost for copying the object.
If you class is further a viable monitor you definitely want to return the object by value because otherwise the object can be mutated before the caller had any chance to copy it.
Basically, none of the choices is ideal. When in doubt, I return by value unless the object is known to be expensive to copy in which case I might return by const&.
Returning by reference or const reference has no speed difference - both are very fast as they just return a reference to the original object, no copying is involved.
An object returned by (non-const) reference can be modified through that reference. In your specific example, mString is public, so it can be modified anyway (and directly). However, the usual approach with getters and setters (and the primary reason for their introduction) is encapsulation - you only allow access to your data members through the getter/setter, so that you can detect invalid values being set, respond to value changes and just generally keep the implementation details of your class hidden inside it. So getters normally return by const reference or by value.
However, if you return by const reference, it binds you to always keep an instance of std::string in your class to back up the reference. That is, even if you later want to redesign your class so that it computes the string on the fly in the getter instead of storing it internally, you can't. You'd have to change your public interface at the same time, which can break code using the class. For example, as long as you return by const-reference, this is perfectly valid code:
const std::string *result = &aSample.Get();
This code will of course produce a dangling pointer no longer compile if Get() is changed to return by value instead of const reference. (thanks to Steve Jessop for correcting me)
To sum up, the approach I would take is to make mString private. Get() can return by value or by const-reference, depending on how certain you are that you'll always have a string stored. The class would then look like this:
class sample
{
std::string mString;
public:
void Set(const std::string &s)
{
mString = s;
}
std::string Get() const
{
return mString;
}
};
The most common thing to do here would be to return the value as a const-reference, then you can use a reference or copy the value as necessary:
const std::string& Get() const
{
return mString;
}
sample mySample;
const std::string &refString = mySample.Get(); // Const-reference to your mString
const std::string copyString = mySample.Get(); // Copy of your mString
If you really need to return a copy of the string, then you can avoid copying the string return value by utilising "The Most Important Const":
sample mySample;
const std::string &myString = mySample.Get();
// myString is now valid until it falls out of scope, even though it points to a "temporary" variable
Return it as a reference. If a copy is needed, it certainly can be made from that reference.

Will I break code when returning a copy instead of a const reference

A framework I need to work with defines a simple mutex class that can store the mutex owner's name as an aid in debugging:
class mutex
{
public:
explicit mutex(const std::string& mutex_owner = "");
bool acquire() const;
bool release() const;
const std::string& get_name() const {return owner_name_;}
// ...
private:
std::string owner_name_;
// ...
};
I have just changed a few algorithms making the mutex type a template parameter so that I can pass in this one for performance reasons, if locking isn't needed:
class non_mutex
{
public:
explicit non_mutex(const std::string& mutex_owner = "") {}
bool acquire() const {return true;}
bool release() const {return true;}
std::string get_name() const {return "";}
};
Since this one does not store a name (there's no need to debug this), I changed the get_name() member function to return a std::string, rather than a const std::string&.
Now my question is: Could this (silently) break anything? The code compiles just fine, and seems to run fine, too, but there's few tests in this codebase, and this function is mostly only used if something goes amiss, rather than regularly.
What are the cases when this change could trigger runtime failures?
Note that this is a C++03 environment, but I'd be interested in C++11 answers, too.
The one that returns by value could potentially throw a bad alloc, the reference one is no-throw. So this could be a problem.
Also, there is a potential for them to call different overloads and traits would specialize differently, but I wouldn't worry about this.
Well, you are no longer returning a constant. You are returning a temporary.
Theoretically this could allow the user to misuse the return value? Perhaps?
Btw. I would solve the issue this way:
static std::string empty_string;
const std::string& get_name() const { return empty_string; }
For silent breakages, one difference is the lifetime of the object returned / referred to by the return. For example, consider the following code:
const string &stupid_user(const string &s) { return s; }
const string &name = stupid_user(mtx.get_name());
mtx.acquire();
std::cout << name;
Now, if mtx has type mutex then this prints the name of the mutex's current owner after the acquire. If mtx has type non_mutex then it has undefined behavior (the const reference does not extend the life of the temporary in this case). Undefined behavior obviously allows that it might pass your tests.
With a less stupid user:
const string &name = mtx.get_name();
mtx.acquire();
std::cout << name;
Now the behavior with mutex is that it prints the new owner, with non_mutex it prints the old owner. Maybe your tests catch that and maybe they don't, but if the calling code assumed one and you supply a type for which it is the other, then you have silently broken the calling code.
Or how about:
auto &&name = mtx.get_name();
mtx.acquire();
std::cout << name;
I think this behaves the same as the non-stupid user, but I'm not sure.
If you (or future visitors to this question) are interested in noisy breakages then it depends how you defined the allowed expressions for use of your Mutex concept (which you're hoping the two classes you present both satisfy).
For example if the expression &mtx.get_name() is allowed, then non_mutex does not satisfy the requirements of the concept.
If you didn't allow that expression, then perhaps non_mutex does satisfy the requirements -- look closely at what expressions are allowed that involve calls to get_name. If all you required is that its return value is "convertible to string" or some such, then you're fine.
If you didn't define the requirements on the template parameter in terms of allowed expressions, but instead did so in terms of what member function signatures and return types it has then (a) you made a mistake, that's not how template-based compile-time polymorphism is supposed to work and (b) non_mutex doesn't have the same member function signatures and return types.
I don't feel there is any problem with your changes. Both get_name() returns non-modifiable lvalue; attempt to modify them results in compiler error in C++03.
If you want to be pedantic, you can always make a choice based on SFINAE since you have templatized the code. With that you can completely remove non_mutex::get_name().

Returning references from a C++ methods

Dear friends, i'm concerned if i'm making a bad use of references in C++
In the following method GCC complains warning "reference to local variable ‘me’ returned"
MatrizEsparsa& MatrizEsparsa::operator+(MatrizEsparsa& outra){
MatrizEsparsa me(outra.linhas(),outra.colunas());
return me;
}
But, with the following changes the warning disappears:
MatrizEsparsa& MatrizEsparsa::operator+(MatrizEsparsa& outra){
MatrizEsparsa me(outra.linhas(),outra.colunas());
MatrizEsparsa &ref = me;
return ref;
}
Is the former method ( returning the 'ref' variable ) correct\acceptable ?
No. ref still refers to me which will be destroyed at the end of the call.
You should return a copy of your result (not prefixed by &).
MatrizEsparsa MatrizEsparsa::operator+(const MatrizEsparsa& outra) const {
return MatrizEsparsa(outra.linhas(),outra.colunas());
}
I also added two const specifiers (to the parameter and to the method) since I doubt outra or the calling instance need to be modified in this case. (I could be wrong, but then your operator+ would have a weird semantic)
By doing what you did, you just made the code more complex. The compiler probably was confused and couldn't warn you about your possible mistake.
Usually, when you have to use clever tricks to do simple things, it means something is wrong.
I think you're mistaking your operators.
There are 2:
struct Foo
{
Foo& operator+=(Foo const&);
Foo operator+(Foo const&) const;
};
As you notice, the first returns a reference to itself, the second does not.
Also, in general, the second should be written as a free function.
Foo operator+(Foo const&, Foo const&);
This can be automated, because it's cumbersome, using Boost.Operators:
struct Foo: boost::addable<Foo>
{
Foo& operator+=(Foo const& rhs)
{
// add
return *this;
}
};
The little boost::addable magic will automatically generate the + implementation based on Foo::operator+=.
It is not acceptable. It is actually the same problem: returning a non-const reference to an local object that will be destroyed after returning the method.
No, you must return a value here, ideally a const value. See Effective C++, Item 21.
I suggest the following interface:
const MatrizEsparsa operator+(const MatrizEsparsa& left, const MatrizEsparsa& right);
Note that everything is either a const reference or a const value. Returning a const value is not as important as returning a value or declaring the parameters as const references, but the arguments of Scott Meyers have convinced me, although no one follows them.
You can't return the reference since the object you are referencing will get destroyed outside of your control. Either put "me" as a member variable of MatrizEsparsa so that it will persist after execution of the function else return a pointer, or a boost smart_ptr, that points to the object.
Seeing as this is a + operator though, you probably want to return a value rather than a reference to a variable internal to the function.