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;

Тогда это должно работать.

Другие вопросы по тегам