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.
Related
Can I typecast callback functions?
I like to write a library that registers and calls certain callback functions.
int MyCaller::add_callback_function(int (*callback_function)(), byte behaviour) {
this->callback = callback_function;
}
void MyCaller::run() {
int result = this->callback();
}
// ....
int get_number() { return 42; }
MyCaller my_caller;
my_caller.add_callback_function(get_number, 0);
my_caller.run();
However, I would also like to support callback_functions that output a boolean.
bool get_bool() { return true; }
MyCaller my_caller;
my_caller.add_callback_function(get_number, 0);
my_caller.run();
If I try this, my code seems to run fine, but gcc will give a warning: invalid conversion from 'bool (*)()' to 'int (*)()' [-fpermissive].
To avoid this warning, I overloaded my add_callback_function with a slightly different signature:
void MyCaller::add_callback_function(bool (*callback_function)(), byte behaviour) {
// ...
}
However, I'm lost from this point onward. I expected that I could cast any boolean to an integer, and call the original method:
void MyCaller::add_callback_function(bool (*callback_function)(), byte behaviour) {
this->add_callback_function(static_cast<int (*)()>(callback_function), byte behaviour);
}
However, this gives an error: invalid static_cast from type 'bool (*)()' to type 'int (*)()'.
So I seem to be doing something wrong.
Is there a clean way to do this?
For bonus points: My code stores an array of callback functions, and I like to be able to optionally add a context parameter (to e.g. allow calling methods besides functions). I plan to store all these callbacks (with different signatures) as a int (*)(), and typecast them to their proper form before calling them. Would that be the best way, or are there other (perhaps better) ways to handle this?
The alternative I can think of is to only support one very specific callback signature, but that forces users to write wrappers. I like to put that burden on the library.
You can cast one function pointer type to another, but you can only call it if you cast it to the real function pointer type. You can only store them as the wrong signature.
Calling them any other way results in undefined behavior. The most likely symptom will depend on your platforms current calling convention. But really, just don't do it.
The easiest correct solution is to store a
std::function<int()>
this isn't a function pointer, but can store any callback (including a function pointer) that can be copied, moved, and invoked with zero arguments and returns something compatible with an int (which a bool qualifies as).
std::function can also store objects with state. For example:
struct Foo {
int count = 0;
int callback(){ return ++count; }
};
Foo foo;
std::function<int()> f = [&foo]{ return foo.callback(); };
naturally you become responsible for lifetime. Look up "C++ lambdas" to understand the above syntax.
I'm reading the code of ROS.
In the file ros_comm/roscpp/include/ros/subscriber.h, I see such a piece of code:
operator void*() const { return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0; }
Well, (void *)0 can be regarded as NULL in C, but what does (void *)1 mean?
If a class Foo contains this function, it means that we can code like this:
Foo foo;
void *ptr = foo;
Right? So does it mean that void *ptr = (void *)1 is possible? What does this mean?
This is an old trick to avoid problems with implicit conversions to bool from before explicit contextual conversions were introduced in C++11. It's intended to be used to check validity:
Subscriber my_subscriber = someFunction();
if (!my_subscriber) {
// error case
}
The important point is that no built-in conversion exists from void* to integer types, but one does exist from bool to integer types. At the same time, a built-in conversion from void* to bool exists. That means that if you define an implicit conversion to bool, then the following is surprisingly valid:
void my_func(int i);
void another_func() {
Subscriber sub = something();
my_func(sub);
}
Defining a conversion to void* avoids that issue.
These days that trick is obsolete though. C++11 introduced explicit conversions. explicit conversions to bool are considered in the conditions of if and loops, but aren't considered in other problematic cases. That means that these days that conversion should be written as:
explicit operator bool() const { return impl_ && impl_->isValid(); }
It shows that either the person who wrote the code isn't very well acquainted with the language or tools they're using, or the code has been around for a long, long time and been hacked on by different people, presumably having undergone a C-to-C++ transition at some time in the past, still carrying some legacy API contract (expecting a void*) which may be troublesome to change.
There is no good reason to do such a thing, if you look at the source. impl_ is a boost::shared_ptr<Impl> which implements operator bool, and Impl::isValid returns bool, too. There's no reason to use, or return anything but bool anywhere.
Basically, this is a contorted (and possibly dangerous) way of writing:
return impl_ && impl_->isValid();
my question is return; the same as return NULL; in C++?
I understand that in C++, return NULL; is the same as return 0; in the context of pointers. Obviously for integers, this is not the case as NULL cannot be added, subtracted, etc. And that it is encouraged by some to use 0 instead of NULL for pointers because it is more convenient for portability. I'm curious if this is another instance where an equivalence occurs.
I suspect that they are equivalent because return; is saying return 'nothing' and NULL is 'nothing.' However, if someone can either confirm or deny this (with explanation, of course), I would be very grateful!
is return; the same as return NULL; in C++?
No.
return is used to "break" out from a function that has no return value, i.e. a return type of void.
return NULL returns the value NULL, and the return type of the function it's found in must be compatible with NULL.
I understand that in C++, return NULL; is the same as return 0; in the context of pointers.
Sort of. NULL may not be equivalent to 0, but it will at least convert to something that is.
Obviously for integers, this is not the case as NULL cannot be added, subtracted, etc.
You can perform addition and subtraction to pointers just fine. However, NULL must have integral type (4.10/1 and 18.1/4 in C++03) anyway so it's moot. NULL may very well be a macro that expands to 0 or 0UL.
Some modern compilers will at least warn you if it was actually NULL you wrote, though.
And that it is encouraged by some to use 0 instead of NULL for pointers because it is more convenient for portability. I'm curious if this is another instance where an equivalence occurs.
No. And I disagree with this advice. Though I can see where it's coming from, since NULL's exact definition varies across implementations, using NULL will make it much easier to replace with nullptr when you switch to C++11, and if nothing else is self-documenting.
return with no expression works only if your function is declared void, in a constructor, or in a destructor. If you try to return nothing from a function that returns an int, a double, etc., your program will not compile:
error: return-statement with no value, in function returning ‘int’
According to §6.6.3/2 of C++11:
A return statement with neither an expression nor a braced-init-list can be used only in functions that do not return a value, that is, a function with the return type void, a constructor (12.1), or a destructor (12.4).
(thanks sftrabbit for the excellent comment).
return, return 0 and return NULL are not the same.
return is only valid with functions returning void, e.g.:
void func(...);
return 0 is for functions returning some int type, e.g.:
unsigned long func(...);
although it works with floating point types as well:
double func(...) { ... return 0; }
return NULL is for functions returning some pointer type, e.g.:
Something *func(...);
It works like a void function, where the return will simply exit the function and return nothing at all. This has been asked before.
There is a difference in the resulting machine code:
return will just put the instruction pointer back to where the caller came from.
return 0 or return NULL will put 0 on the stack, and then put the instruction pointer back to where the caller came from. (In C, NULL is usually mapped to 0, although that can (may?) differ in different implementations. In C++, NULL is not supposed to be used).
const testNullParity = () => {
return null
}
const testNullParity2 = () => {
return
}
console.log(testNullParity()) //null
console.log(testNullParity2()) //undefined
in javascript, return is short for return undefined as null and undefined are two different types, but they are loosely equal ie. testNullParity() == testNullParity2() is true but not testNullParity() === testNullParity2()
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.
I was looking into how std::tr1::shared_ptr<> provides the ability to cast to bool. I've got caught out in the past when trying to create a smart pointer that can be casted to bool as the trivial solution, ie
operator bool() {
return m_Ptr!=0;
}
usually ends up being implicitly castable to the pointer type (presumably by type promotion), which is generally undesirable. Both the boost and Microsoft implementations appear to use a trick involving casting to an unspecified_bool_type(). Can anyone explain how this mechanism works and how it prevents implicit casting to the underlying pointer type?
The technique described in the question is the safe bool idiom.
As of C++11, that idiom is no longer necessary. The modern solution to the problem is to use the explicit keyword on the operator:
explicit operator bool() {
return m_Ptr != nullptr;
}
The trick works like this. You define all this inside your smart pointer type (in this case, shared_ptr):
private:
struct Tester
{
Tester(int) {} // No default constructor
void dummy() {}
};
typedef void (Tester::*unspecified_bool_type)();
public:
operator unspecified_bool_type() const
{
return !ptr_ ? 0 : &Tester::dummy;
}
ptr_ is the native pointer inside the smart pointer class.
As you can see, unspecified_bool_type is a typedef to a type that cannot be accessed by any external code, since Tester is a private struct. But calling code can use this (implicit) conversion to a pointer type and check whether it is null or not. Which, in C++, can be used as a bool expression.
Usually what it returns is a member pointer. Member pointers can be treated like a bool but don't support many of the implicit conversions which bool does.