Что означает (void *) 1?

Я читаю код ROS.

В файле ros_comm/roscpp/include/ros/subscriber.h я вижу такой фрагмент кода:

operator void*() const { return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0; }

Ну, (void *)0 можно рассматривать как NULL в C, но что означает (void *)1?

Если класс Foo содержит эту функцию, это означает, что мы можем кодировать так:

Foo foo;
void *ptr = foo;

Правильно? Значит ли это, что void *ptr = (void *)1 возможен? Что это значит?

Ответ 1

Это старый прием, позволяющий избежать проблем с неявными преобразованиями в bool до появления explicit контекстных преобразований в С++ 11. Он предназначен для проверки действительности:

Subscriber my_subscriber = someFunction();
if (!my_subscriber) {
    // error case
}

Важным моментом является то, что не существует встроенного преобразования из типа void* в целочисленные типы, но существует тип от bool до целочисленных типов. В то же время существует встроенное преобразование из void* в bool. Это означает, что если вы определяете неявное преобразование в bool, то на удивление верно следующее:

void my_func(int i);

void another_func() {
    Subscriber sub = something();
    my_func(sub);
}

Определение преобразования в void* позволяет избежать этой проблемы.


В наши дни этот трюк устарел. С++ 11 ввел explicit преобразования. explicit преобразования в bool рассматриваются в условиях циклов if и, но не рассматриваются в других проблемных случаях. Это означает, что в наши дни это преобразование должно быть записано как:

explicit operator bool() const { return impl_ && impl_->isValid(); }

Ответ 2

Это показывает, что либо человек, который написал код, не очень хорошо знаком с языком или инструментами, которые они используют, либо код был в течение долгого и долгого времени и был взломан разными людьми, по-видимому, подвергся Переход от C к С++ в прошлом, все еще несущий некоторый устаревший контракт API (ожидающий void*), который может быть проблематичным для изменения.

Нет веских причин делать такие вещи, если вы посмотрите на источник. impl_ является boost::shared_ptr<Impl> который реализует operator bool, и Impl::isValid возвращает bool. Там нет никаких оснований для использования или возврата чего-либо, кроме bool любом месте.

По сути, это искаженный (и, возможно, опасный) способ написания:

return impl_ && impl_->isValid();