I'm curious, is:
bool State::operator<(const State* S)
{
return this->operator<(*dynamic_cast<const State *>(S));
}
exactly the same as:
bool State::operator<(const State* S)
{
return this->operator<(*(S));
}
For reference the this->operator< being called is:
bool State::operator<(const State& S)
{
return this->reward < S.reward ? true : false;
}
Which one is more "correct" and type safe / secure to use or, is there any actual difference ?
No, the first one casts the pointer to itself, which doesn't really do anything, and then calls const State* overload, which results in an infinite loop. You don't need dynamic_cast until you need to downcast at runtime — there is no downcasting here, so
return this->operator<(*S);
is the only thing to do.
Assuming you have a typo and you mean to compare this:
*dynamic_cast<const State *>(s)
...to this:
*s
...where s has compile-time type const State *, there is no difference at all.
It is conceivable that the former could be slightly slower if your compiler does not notice that they are compile-time equivalent.
I would avoid the former on the grounds that anybody reading it will wonder what you are thinking.
Related
I have two versions of the same static member function: one takes a pointer-to-const parameter and that takes a pointer-to-non-const parameter. I want to avoid code duplication.
After reading some stack overflow questions (these were all about non-static member functions though) I came up with this:
class C {
private:
static const type* func(const type* x) {
//long code
}
static type* func(type* x) {
return const_cast<type*>(func(static_cast<const type*>(x)));
}
public:
//some code that uses these functions
};
(I know juggling with pointers is generally a bad idea, but I'm implementing a data structure.)
I found some code in libstdc++ that looks like this:
NOTE: these are not member functions
static type* local_func(type* x)
{
//long code
}
type* func(type* x)
{
return local_func(x);
}
const type* func(const type* x)
{
return local_func(const_cast<type*>(x));
}
In the first approach the code is in a function that takes a pointer-to-const parameter.
In the second approach the code is in a function that takes a pointer-to-non-const parameter.
Which approach should generally be used? Are both correct?
The most important rule is that an interface function (public method, a free function other than one in a detail namespace, etc), should not cast away the constness of its input. Scott Meyer was one of the first to talk about preventing duplication using const_cast, here's a typical example (How do I remove code duplication between similar const and non-const member functions?):
struct C {
const char & get() const {
return c;
}
char & get() {
return const_cast<char &>(static_cast<const C &>(*this).get());
}
char c;
};
This refers to instance methods rather than static/free functions, but the principle is the same. You notice that the non-const version adds const to call the other method (for an instance method, the this pointer is the input). It then casts away constness at the end; this is safe because it knows the original input was not const.
Implementing this the other way around would be extremely dangerous. If you cast away constness of a function parameter you receive, you are taking a big risk in UB if the object passed to you is actually const. Namely, if you call any methods that actually mutate the object (which is very easy to do by accident now that you've cast away constness), you can easily get UB:
C++ standard, section § 5.2.11/7 [const cast]
[ Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a
const_cast that casts away a const-qualifier may produce undefined
behavior. —end note ]
It's not as bad in private methods/implementation functions because perhaps you carefully control how/when its called, but why do it this way? It's more dangerous to no benefit.
Conceptually, it's often the case that when you have a const and non-const version of the same function, you are just passing along internal references of the object (vector::operator[] is a canonical example), and not actually mutating anything, which means that it will be safe either way you write it. But it's still more dangerous to cast away the constness of the input; although you might be unlikely to mess it up yourself, imagine a team setting where you write it the wrong way around and it works fine, and then someone changes the implementation to mutate something, giving you UB.
In summary, in many cases it may not make a practical difference, but there is a correct way to do it that's strictly better than the alternative: add constness to the input, and remove constness from the output.
I have actually only ever seen your first version before, so from my experience it is the more common idiom.
The first version seems correct to me while the second version can result in undefined behavior if (A) you pass an actual const object to the function and (B) the long code writes to that object. Given that in the first case the compiler will tell you if you're trying to write to the object I would never recommend option 2 as it is. You could consider a standalone function that takes/returns const however.
I was playing with some code to remove constant-ness of variable.
int *i = new int(202);
int *j = new int(402);
int *const iptr = i; // Constant pointer
//iptr = j ; // Not allowed. Constant pointer cannot point to another location.
(*iptr)++; // Allowed
const_cast<int *>(iptr) = j;
cout<< *iptr // prints 402
It works as expected but when I try to remove constantness of "this" pointer, Compiler doesnt allow it, i.e. it shows squiggling lines underneath the const_cast statement.
class A
{
public:
A(A * obj)
{
const_cast<A *>(this) = obj;
}
};
When I hovered mouse (I am using VS2014) over "this" and "iptr" from earlier code, I could see the type is same i.e. <classname> *const
Can anybody please explain what is going on under the hood?
Cheers,
Saket
I am afraid you did not understand what const_cast is for.
In C++, const is used in two instances:
a const object logical value cannot be changed (and, barring mutable fields, its bitwise value cannot be changed either)
const* or const& are read-only pointers or references
const_cast is not about changing const objects, it's about modifying non-const objects through read-only pointers or references
Bear in mind though that shooting yourself in the foot is easy, because when you get a const& how do you know whether the original object is const or not ? You do not. And if you attempt to change one that is const, a unicorn appears, or maybe the devil (also know as Undefined Behavior: anything may happen).
Now, the correlation with this is tricky. Strictly speaking this is an r-value (meaning it can only appear as-is on the R ight-hand side of =), though it is often described as simply being const for simplicity's sake, so in a constructor of A this is described as having type A* const. Thankfully for us, even in this approximation const_cast is a bad idea since the original object is const.
Therefore, the recommendation is:
Junior: Do not use const_cast, reinterpret_cast or C-style casts (because it is not obvious when they desugar to one of the first two).
Senior: You are not experienced enough.
Expert: Come on! How can you claim you are an expert and attempt to use them ?
this is not an l-value.
You cannot assign it to point to something else.
You can do *this = *obj; which does not require a const_cast
You can do a const_cast<A*>(this) to override constness, and as with any other const_cast is fraught with danger, but it would enable you to perform a const/non-const overload without having to duplicate the implementation e.g.
T& A::get()
{
// some complex code to find the right reference, assigning to t
return t;
}
const T& A::get() const
{
// implement in terms of above function
return (const_cast<A*>(this))->get(); // invokes above
// and automatically converts the reference to const
}
Here is a fragment of code:
bool EqualsA(const Foo& a, const Foo& b)
{
return a == b;
}
bool EqualsB(const Foo& a, const Foo& b)
{
const bool result = a == b;
return result;
}
int MethodA()
{
return GetValue() * GetOtherValue();
}
int MethodB()
{
const int result = GetValue() * GetOtherValue();
return result;
}
I wanted to know if there is any difference in returning values in these two different ways (instant return or store result in a variable). I think that storing is better for debugging but is there any performance loss (I don't think there is) or any other pros and cons for using one of those.
The compiler is free to optimize away the local variable so the performance is going to be the same.
In a lot of code analysis tools this is marked as a code smell and I would tend to agree. Debuggers can be made to see the return value on the stack so the local variable doesn't buy anything.
Under the reasonable assumption that the value returned by the selected overload of operator == for objects of type Foo is of type bool, a decent compiler will optimize your temporary store away when heavy optimization options are used, so as for performance, it does not matter.
My advice is to choose the form that makes your code more readable or more convenient to maintain or debug for you.
There will almost certainly be no difference. The compiler is allowed to do whatever it likes to your code as long as the program behaves as-if it were as you wrote it. So any nice compiler will get rid of the pointless initializations.
However, it's possible for there to be a situation it can't make this initialization disappear. If, for example, an operator* overload used for GetValue() * GetOtherValue() returns a class type result by const reference, the constructor of that class type might have some side effects. If it does, the compiler can't get rid of the initialization because it changes the observable behaviour of the program.
But why would that not also be the case if the operator* returned by value? Then this would be a candidate for copy elision, and the compiler could get rid of the construction regardless of whether it had side effects or not.
I've seen a nice trick made by an boost Implementation, they somehow use the overloading of the () operator to evaluate an instance of the class boost::system::error_code to an bool value
class error_code
{
...
typedef void (*unspecified_bool_type)();
static void unspecified_bool_true() {}
operator unspecified_bool_type() const // true if error
{
return m_val == 0 ? 0 : unspecified_bool_true;
}
...
}
This results in the possibility to check for an error like this
...
boost::system::error_code err
some_boost_func(err);
if(err)
{
//handle error
}
....
So i keep asking myself.. what happend there?
This seems to somehow relate to the use of function pointers...
What happens if i call err does this evaluate the function itself or the function pointer?
But how can a void (*unspecified_bool_type)(); function return a value in
return m_val == 0 ? 0 : unspecified_bool_true;
It really has little (or nothing) to do with core functionality of function pointers specifically. It is a trick that allows one to write a "safe" boolean-like conversion for the class.
When one wants some class to be usable under if (and generally in logic contexts), one typically makes it convertible to bool. As in
class Error {
public:
operator bool() const { /* whatever */ }
};
and now you can do
Error err;
...
if (err) // automatically intepreted as `if (err.operator bool())`
...
However, since bool type is an integral type in C++, this might lead to undesirable consequences, when someone accidentally writes something like
int i = err;
or uses err in an arithmetic expression and it quietly compiles.
For this reason, in many cases people prefer to introduce a conversion to pointer type, instead of conversion to bool, as in
class Error {
public:
operator void *() const {
// Return null pointer for `false` and any non-null pointer for `true`
}
};
This is better since one can use it under if, but one can't make the previous mistake with int. I.e.
if (err) // automatically interpreted as `if (err.operator void *() != 0)`
...
will compile and work as intended, since the compiler will automatically convert err object to pointer type.
However, such conversion will be automatically applied in pointer contexts as well (in addition to boolean contexts), meaning that one can still accidentally do
void *p = err;
or
free(err);
and it will quietly compile. This is also undesirable.
To make it more difficult to accidentally misuse such error class, it is a good idea to use some more "exotic" pointer type, like pointer to a function. This is exactly what you see in the code you quoted. The unspecified_bool_type is used as a pointer-based pseudo-boolean type. Null value is returned for false and pointer to a dummy unspecified_bool_true function is returned for true. The function unspecified_bool_true is never called and never intended to be called. It only exists to reserve some unique pointer value to be used as true return.
In some cases people take it one step further and use an even more "exotic" pointer type: pointer-to-class-member type. But for most applications pointer to function is "exotic" enough.
Given this prototype which does a Endian conversion:
time_t Flip( time_t );
I would like to use the return value in a function that takes a BYTE* as an argument.
Something like this:
SetBytesAt( 0, (BYTE*)&(Flip( t )) );
But this does not compile. Gives me this error "& requires l-value".
If the () are removed from around the Flip function, the same error is generated.
Now, I know that I can just do this:
time_t temp_t = Flip( t );
SetBytesAt( 0, (BYTE*)&temp_t );
But it seems to me that I should be able to accomplish the same thing without the temporary temp_t variable.
Unfortunately, no. You cannot take the address of a temporary (more correctly, an r-value). That's just the way the language has been defined.
Don't try this at home.
template <typename T>
class AddressableTemporary
{
public:
AddressableTemporary(T const value)
: value_(value)
{
}
operator T*() { return &value_; }
private:
T value_;
};
template <typename T>
AddressableTemporary<T> MakeAddressable(T value)
{
return AddressableTemporary<T>(value);
}
Used as:
int F() { return 42; }
void G(int const* const p) { std::cout << *p; }
int main()
{
G(MakeAddressable(F()));
}
But really, don't do this. Either use a variable, or write a wrapper function that encapsulates usage of the variable, or rework your code so that you don't need to worry about this (e.g., modify the function so that it takes, say, a const reference).
You need to use a temporary variable. You can only take address of l-values. There is no way to take address of a return value.
On some platforms, return value is only stored in a register and hence doesn't even have an address. You need to store it in memory before you can pass its address to another function.
To the best of my knowledge, that is not possible in C++.
Ask yourself this: how will you access the modified result after SetBytesAt returns?
Return values are normally copied (or moved) to an actual variable in the caller function. The temporary space reserved for the returned value is no longer available after the function returns. Theoretically, you would be stack memory that is no longer valid. This mistake happens in practice when returning references to local variables.
Actually, it became possible in C++11. There, r-value references were introduced. However, I don't know, which compiler does it already.
You can't, for the exact reason given by the error message - & requires l-value.
The call Flip(t) is not an l-value, so it's impossible.
It's no big deal to do what you want, but it's unclean.
Here goes:
template< class Type >
Type const& ref( Type const& v ) { return v; }
int main()
{
time_t t = blah blah;
SetBytesAt( 0, const_cast<Byte*>( reinterpret_cast<Byte const*>( &ref( Flip( t ) ) ) ) );
}
Technically this can work if SetBytesAt copies the bytes, but if SetBytesAt stores the pointer, and that pointer is later used, then it's undefined behavior.
Anyway, don't do that.
Now I'll list what's wrong with the original concept:
Discarding type knowledge by using typeless pointer argument.
→ Means a lot of extra work because the type is not known.
Discarding const knowledge by using pointer to non-const argument.
→ Means a lot of extra work because the constness is not known.
Flipping byte order of data = ungood except in low level network code.
→ Means a lot of extra work because the byte order is not known.
So, again, don't do that.
Instead, do the opposite: preserve type information, preserve constness information, and don't mess with the raw bytes.