nullptr
От: Roman Odaisky Украина  
Дата: 28.08.06 11:35
Оценка:
Недавно наткнулся на проблему при заполнении последовательности указателей нулевыми значениями. std::fill сказал мне, что NULL ему не годится, поскольку int не приводится к типу X *. Тогда я решил, наконец, реализовать nullptr. Обратившись к коллективному сознанию, написал следующее:
class NullptrType: boost::noncopyable
{
public:
    template <class X>
    operator X* () const
    {
        return 0;
    }

    template <class T, class C>
    operator T C::* () const
    {
        return 0;
    }

    static NullptrType const& _the()
    {
        static NullptrType const the;
        return the;
    }

private:
    NullptrType()
    {
    }

    void operator &();
};

namespace
{
    NullptrType const& nullptr = NullptrType::_the();
}

Но тут же появились вопросы:
1. Зачем он noncopyable?
2. Зачем у него скрыт дефолтный конструктор?
(Какие варианты неправильного применения это помогает отловить? В C++09 nullptr ведь и копируется, и создается?)

3. (MSVC71) Как бы сделать, чтоб отладчик не заходил в эти операторы по F11? Может, есть какая-то прагма? А то F11 уже влезает в чересчур много мест: begin()/end(), iterator -> const_iterator, custom_cast, NullptrType -> X * и т. п., которые давно отлажены или, как в данном случае, не делают вообще ничего интересного;
4. Стоит ли #define NULL nullptr? В конце концов, программа вправе рассчитывать на #define NULL 0. Я сделал дефайн, что помогло выловить N-ное количество неуставных использований NULL и прояснить код, правильно расставив NULL и literal 0 — может, теперь дефайн следует убрать (и s/NULL/nullptr/g — ох и коммит будет )?
5. Есть вариант впихнуть туда член void* dummy, чтобы sizeof(nullptr) == sizeof(void *). Стоит ли?
До последнего не верил в пирамиду Лебедева.
Re: nullptr
От: Андрей Россия  
Дата: 28.08.06 11:55
Оценка: 1 (1) +1
Здравствуйте, Roman Odaisky, Вы писали:

skip

а не проще было написать std::fill(..., ..., static_cast<X*>(0))?

Re: nullptr
От: zaufi Земля  
Дата: 28.08.06 12:00
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Недавно наткнулся на проблему при заполнении последовательности указателей нулевыми значениями. std::fill сказал мне, что NULL ему не годится, поскольку int не приводится к типу X *. Тогда я решил, наконец, реализовать nullptr. Обратившись к коллективному сознанию, написал следующее:

RO>
RO>class NullptrType: boost::noncopyable
RO>{
RO>public:
RO>    template <class X>
RO>    operator X* () const
RO>    {
RO>        return 0;
RO>    }

RO>    template <class T, class C>
RO>    operator T C::* () const
RO>    {
RO>        return 0;
RO>    }

RO>    static NullptrType const& _the()
RO>    {
RO>        static NullptrType const the;
RO>        return the;
RO>    }

RO>private:
RO>    NullptrType()
RO>    {
RO>    }

RO>    void operator &();
RO>};

RO>namespace
RO>{
RO>    NullptrType const& nullptr = NullptrType::_the();
RO>}
RO>

RO>Но тут же появились вопросы:
RO>1. Зачем он noncopyable?

а зачем ему быть копируемым если на всю прогу нужен только 1 экземпляр данного класса?

RO>2. Зачем у него скрыт дефолтный конструктор?

чтобы ни кто не создавал ненужных экземпляров... одного nullptr вполне достаточно -- все что требуется от данного экземпляра в нужный момент приводиться к нулевому указателю на любой тип (включая datamemberов любых классов)

RO>(Какие варианты неправильного применения это помогает отловить? В C++09 nullptr ведь и копируется, и создается?)

не то чтоб неправильного... просто незачем копировать данный объект -- и все это сделано чтобы избежать генерации _ненужного_ кода (без которого всегда можно обойтись)

RO>4. Стоит ли #define NULL nullptr? В конце концов, программа вправе рассчитывать на #define NULL 0. Я сделал дефайн, что помогло выловить N-ное количество неуставных использований NULL и прояснить код, правильно расставив NULL и literal 0 — может, теперь дефайн следует убрать (и s/NULL/nullptr/g — ох и коммит будет )?


мое ИМХО: я бы сделал вообще `#undef NULL` и все вхождения NULL позаменял бы на `0'! А в тех редких случаях когда int не приводится в pointer использовал бы nullptr...

RO>5. Есть вариант впихнуть туда член void* dummy, чтобы sizeof(nullptr) == sizeof(void *). Стоит ли?

ну стоит конечно если у тебя в коде повсюду натыкано `sizeof(NULL)` что мне лична представляется малореалистичным
Re[2]: nullptr
От: zaufi Земля  
Дата: 28.08.06 12:08
Оценка:
Здравствуйте, Андрей, Вы писали:

А>Здравствуйте, Roman Odaisky, Вы писали:


А>skip


А>а не проще было написать std::fill(..., ..., static_cast<X*>(0))?


`std::fill(..., ..., nullptr)' выглядит красивее/эстетичнее/читабельнее

правда код делается менее эффекивным при выключенном оптимизаторе... но в релизе все буит ОК
Re[2]: nullptr
От: Centaur Россия  
Дата: 28.08.06 12:27
Оценка:
Здравствуйте, zaufi, Вы писали:

RO>>Недавно наткнулся на проблему при заполнении последовательности указателей нулевыми значениями. std::fill сказал мне, что NULL ему не годится, поскольку int не приводится к типу X *. Тогда я решил, наконец, реализовать nullptr.


Недавно оборачивал некоторые функции Win32 API. Шаблоны мне сказали, что int к HWND (который есть struct HWND__*) приводить категорически не будут. Тогда я сказал, что у типа HWND есть конструктор по умолчанию и что в качестве NULL буду использовать HWND().

Если соответствующего typedef’а для X* нет, то не сработает, конечно.
Re[3]: nullptr
От: Roman Odaisky Украина  
Дата: 28.08.06 12:27
Оценка:
Здравствуйте, zaufi, Вы писали:

А>>а не проще было написать std::fill(..., ..., static_cast<X*>(0))?


Z>`std::fill(..., ..., nullptr)' выглядит красивее/эстетичнее/читабельнее


Z>правда код делается менее эффекивным при выключенном оптимизаторе... но в релизе все буит ОК


VC 7.1 в релизе, как для static_cast<X *>(0), так и для nullptr, генерит код вроде
mov    DWORD PTR [eax], 0
add    eax, 4
cmp    eax, ecx
jne    опять

так что с этим нормально. Даже лучше, чем memset — не тратим время на выравнивание. Разве что не догадывается анроллить...
До последнего не верил в пирамиду Лебедева.
Re: nullptr
От: Константин Л. Франция  
Дата: 28.08.06 13:08
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

[]

RO>Но тут же появились вопросы:

RO>1. Зачем он noncopyable?
RO>2. Зачем у него скрыт дефолтный конструктор?
RO>(Какие варианты неправильного применения это помогает отловить? В C++09 nullptr ведь и копируется, и создается?)

действительно, зачем?

RO>3. (MSVC71) Как бы сделать, чтоб отладчик не заходил в эти операторы по F11? Может, есть какая-то прагма? А то F11 уже влезает в чересчур много мест: begin()/end(), iterator -> const_iterator, custom_cast, NullptrType -> X * и т. п., которые давно отлажены или, как в данном случае, не делают вообще ничего интересного;


хз )

RO>4. Стоит ли #define NULL nullptr? В конце концов, программа вправе рассчитывать на #define NULL 0. Я сделал дефайн, что помогло выловить N-ное количество неуставных использований NULL и прояснить код, правильно расставив NULL и literal 0 — может, теперь дефайн следует убрать (и s/NULL/nullptr/g — ох и коммит будет )?


думаю, не стоит. Просто можно постепенно переходить на его использование

RO>5. Есть вариант впихнуть туда член void* dummy, чтобы sizeof(nullptr) == sizeof(void *). Стоит ли?


зачем?
Re[2]: nullptr
От: Roman Odaisky Украина  
Дата: 28.08.06 15:39
Оценка:
Здравствуйте, zaufi, Вы писали:

RO>>(Какие варианты неправильного применения это помогает отловить? В C++09 nullptr ведь и копируется, и создается?)

Z>не то чтоб неправильного... просто незачем копировать данный объект -- и все это сделано чтобы избежать генерации _ненужного_ кода (без которого всегда можно обойтись)

Ладно, пусть будет с закрытыми конструкторами. Если где в шаблонах лишнее копирование, будем считать логической ошибкой.

RO>>4. Стоит ли #define NULL nullptr? В конце концов, программа вправе рассчитывать на #define NULL 0. Я сделал дефайн, что помогло выловить N-ное количество неуставных использований NULL и прояснить код, правильно расставив NULL и literal 0 — может, теперь дефайн следует убрать (и s/NULL/nullptr/g — ох и коммит будет )?


Z>мое ИМХО: я бы сделал вообще `#undef NULL` и все вхождения NULL позаменял бы на `0'! А в тех редких случаях когда int не приводится в pointer использовал бы nullptr...


Ну это однозначно зря. Сравни:
char* s = real2str(0, 0, 0);
. . .
delete [] s;
и
char* s = real2str(0., NULL, 0u); // или nullptr
. . .
delete [] s;

RO>>5. Есть вариант впихнуть туда член void* dummy, чтобы sizeof(nullptr) == sizeof(void *). Стоит ли?
Z>ну стоит конечно если у тебя в коде повсюду натыкано `sizeof(NULL)` что мне лична представляется малореалистичным
А sizeof(NULL) может != sizeof(void *) Я опять же размышляю о forward compatibility с C++09...
До последнего не верил в пирамиду Лебедева.
Re[3]: nullptr
От: rusted Беларусь  
Дата: 29.08.06 09:03
Оценка:
Здравствуйте, zaufi, Вы писали:

А>>а не проще было написать std::fill(..., ..., static_cast<X*>(0))?


Z>`std::fill(..., ..., nullptr)' выглядит красивее/эстетичнее/читабельнее


если пишешь только для себя — то может и читабельнее, а вот кому-то другому видящему такой код придется еще смотреть что это за nullptr за такой.
Re[3]: nullptr
От: zaufi Земля  
Дата: 29.08.06 09:27
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>>>4. Стоит ли #define NULL nullptr? В конце концов, программа вправе рассчитывать на #define NULL 0. Я сделал дефайн, что помогло выловить N-ное количество неуставных использований NULL и прояснить код, правильно расставив NULL и literal 0 — может, теперь дефайн следует убрать (и s/NULL/nullptr/g — ох и коммит будет )?


Z>>мое ИМХО: я бы сделал вообще `#undef NULL` и все вхождения NULL позаменял бы на `0'! А в тех редких случаях когда int не приводится в pointer использовал бы nullptr...


RO>Ну это однозначно зря. Сравни:


ну не так уж однозначно
я лична не испытываю необходимости в NULL вообще и по совету Б.Страуструпа использую 0 везде вместа него. Отчасти ввиду того что указателей в моем коде не так уж много (стараюсь сводить их к минимуму).
Re[4]: nullptr
От: Roman Odaisky Украина  
Дата: 29.08.06 09:53
Оценка: 1 (1) +1 :)
Здравствуйте, rusted, Вы писали:

А>>>а не проще было написать std::fill(..., ..., static_cast<X*>(0))?


Z>>`std::fill(..., ..., nullptr)' выглядит красивее/эстетичнее/читабельнее


R>если пишешь только для себя — то может и читабельнее, а вот кому-то другому видящему такой код придется еще смотреть что это за nullptr за такой.


Имя у него говорит само за себя, кроме того, nullptr есть в C++/CLI и в C++09 (будет). Ты еще скажи, что тот другой полезет узнавать, что делает std::fill.
До последнего не верил в пирамиду Лебедева.
Re[2]: nullptr
От: Roman Odaisky Украина  
Дата: 04.09.06 17:22
Оценка: :)
Здравствуйте, zaufi, Вы писали:

RO>>1. Зачем он noncopyable?

Z>а зачем ему быть копируемым если на всю прогу нужен только 1 экземпляр данного класса?

Вот только что оказалось, что копирование ему очень даже полезно.
std::pair<X *, X *> getTwoX()
{
    return std::make_pair(&m_x, nullptr); // std::pair<X *, decltype(nullptr)> -> std::pair<X *, X *>
}

Но я всё еще в сомнениях... Выкинуть эти private или оставить?
До последнего не верил в пирамиду Лебедева.
Re[3]: nullptr
От: Константин Л. Франция  
Дата: 05.09.06 11:01
Оценка: +1
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, zaufi, Вы писали:


RO>>>1. Зачем он noncopyable?

Z>>а зачем ему быть копируемым если на всю прогу нужен только 1 экземпляр данного класса?

RO>Вот только что оказалось, что копирование ему очень даже полезно.

RO>
RO>std::pair<X *, X *> getTwoX()
RO>{
RO>    return std::make_pair(&m_x, nullptr); // std::pair<X *, decltype(nullptr)> -> std::pair<X *, X *>
RO>}
RO>

RO>Но я всё еще в сомнениях... Выкинуть эти private или оставить?
выкинуть
Re: nullptr
От: korzhik Россия  
Дата: 05.09.06 11:47
Оценка: 19 (2)
Здравствуйте, Roman Odaisky, Вы писали:


RO>3. (MSVC71) Как бы сделать, чтоб отладчик не заходил в эти операторы по F11? Может, есть какая-то прагма? А то F11 уже влезает в чересчур много мест: begin()/end(), iterator -> const_iterator, custom_cast, NullptrType -> X * и т. п., которые давно отлажены или, как в данном случае, не делают вообще ничего интересного;


http://www.rsdn.ru/article/vcpp/vcdebug-1.xml#EWGAE
Автор(ы): Александр Шаргин
Дата: 27.01.2002
Файл autoexp.dat — Секция [ExecutionControl]
Re[2]: nullptr
От: Roman Odaisky Украина  
Дата: 06.09.06 11:15
Оценка: 20 (2)
Здравствуйте, korzhik, Вы писали:

K>http://www.rsdn.ru/article/vcpp/vcdebug-1.xml#EWGAE
Автор(ы): Александр Шаргин
Дата: 27.01.2002


В очередной раз убеждаюсь, что на RSDN есть всё!.. и большая часть этого «всего» давно устарела Но теперь, зная ключевые слова, я смог выгуглить это:

http://www.cprogramming.com/debugging/visual-studio-msvc-debugging-NoStepInto.html
До последнего не верил в пирамиду Лебедева.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.