clang 3.5 constexpr несоответствие - ошибки при использовании double, но не int
После ответа с использованием математических констант boost в constexpr и предложения OP использовать шаблонную функцию boost для constexpr
вместо переменной без шаблонов для подавления ошибки лягушки, я решил попытаться выяснить, при каких условиях эта ошибка воспроизводится в лягушке. Давайте попробуем скопировать, к чему расширяется макрос boost:
namespace double_constants{ static const double name = 25; }
static constexpr double SEC3 = double_constants::name;
Это дает следующие ошибки (следуйте по Coliru)
clang++ -std=c++1y -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:5:25: error: constexpr variable 'SEC3' must be initialized by a constant expression
static constexpr double SEC3 = double_constants::name;
^ ~~~~~~~~~~~~~~~~~~~~~~
main.cpp:5:32: note: read of non-constexpr variable 'name' is not allowed in a constant expression
static constexpr double SEC3 = double_constants::name;
^
main.cpp:3:49: note: declared here
namespace double_constants{ static const double name = 25; }
Это нормально, мы ожидали этого. Теперь поменяй double
в int
:
namespace double_constants{ static const int name = 25; }
static constexpr double SEC3 = double_constants::name;
Нет ошибок? Излишне говорить, что я в замешательстве. Я предположил, что ошибка была, потому что переменная определяется как const
вместо constexpr
, если я что-то упустил. Давайте посмотрим на cppreference:
Переменная constexpr должна удовлетворять следующим требованиям:
- это должно быть немедленно построено или присвоено значение.
- параметры конструктора или назначаемое значение должны содержать только литеральные значения, переменные и функции constexpr.
Если бы мы интерпретировали это буквально, то лязгать оправданно, давая ошибку, потому что name
только const
не constexpr
, И видимо double
это LiteralType
так как:
std::cout << std::is_literal_type<double>::value;
выходы 1
, Так почему же Clang перестает жаловаться, если name
является int
и не double
?
PS: не может воспроизвести на GCC.
Для уточнения static
Ключевое слово является ортогональным к вопросу. Так это namespace
, Из того, что я понимаю, макрос повышения не переносит static const
переменная в классе, но в namespace
, Я сузил это до этих четырех случаев:
// Does not compile
const double name = 25;
constexpr int SEC3 = name;
const double name = 25;
constexpr double SEC3 = name;
// Compiles
const int name = 25;
constexpr double SEC3 = name;
const int name = 25;
constexpr int SEC3 = name;
Я не могу потрудиться применить static
в каждой перестановке можно увидеть, если это имеет значение, но я сомневаюсь, что это делает.
1 ответ
Это не ошибка. К сожалению, стандарт C++ имеет разные статические / нестатические правила const для типов с плавающей точкой и целочисленных типов. Посмотри пожалуйста:
Почему статические константные поплавки не допускаются?
Попробуйте constexpr вместо const как в:
namespace double_constants{ constexpr double name = 25; }
а также:
constexpr double name = 25;
constexpr int SEC3 = name;
Тогда это должно работать.