Ответ 1
Это ошибка gcc. Отчет о дефектах 903: константные константные константы указателя указателя, зависящие от стоимости, который представляет собой отчет о дефекте против С++ 11 (он имеет статус CD3), делает его таким что только целочисленный литерал 0
считается константой нулевого указателя.
Он изменил раздел 4.10
[conv.ptr] paragraph 1
среди других изменений:
Константа нулевого указателя является интегральным постоянным выражением (5.19 [expr.const]) prvalue целочисленного типа, который вычисляется до нуля [...]
в
Константа нулевого указателя представляет собой целочисленный литерал (2.14.2 [lex.icon]) со значением 0 [...]
Это указано как несовместимость с С++ 03, из раздела C.2.2
Раздел 4: стандартные преобразования [diff.cpp03.conv], в котором говорится:
Изменить: Только литералы являются целыми константами указателя на указатель
Обоснование: Удаление неожиданных взаимодействий с шаблонами и постоянные выражения
Влияние на оригинальную функцию: Действительный код С++ 2003 может не скомпилироваться или дают разные результаты в этом Международном стандарте, поскольку следующий пример иллюстрирует:void f(void *); // #1 void f(...); // #2 template<int N> void g() { f(0*N); // calls #2; used to call #1 }
Следующий отчет об ошибке gcc [С++ 11] [DR 903] нулевое целочисленное выражение константы должен предпочесть преобразование в указатель, показывает, что команда gcc изначально считала, что это было изменение С++ 17, но позже изменило его действие на С++ 11.
Мы можем видеть в главном редакторе gcc (6.0) это исправлено (видеть его в прямом эфире) и производит диагностику для всех случаев clang делает:
error: could not convert '(1 - 1)' from 'int' to 'std::shared_ptr<int>'
f( 1 - 1 ); // compiles fine in gcc, fails in clang
~~^~~
error: could not convert 'i' from 'const int' to 'std::shared_ptr<int>'
f( i ); // fails to compile in gcc and clang
^
error: could not convert '(0 - 0)' from 'int' to 'std::shared_ptr<int>'
f( i - 0 ); // compiles fine in gcc, fails in clang
~~^~~