简体   繁体   中英

What does (void *)1 mean?

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM