Взгляните на следующий пример кода:
template<bool val>
struct test {
static const int value_a = val;
const int value_b = val;
constexpr int get_value_a() const noexcept { return value_a; }
constexpr int get_value_b() const noexcept { return value_b; }
};
int main(int argc, char** argv) {
auto t = test<true>{};
static_assert(t.value_a);
// static_assert(t.value_b);
static_assert(t.get_value_a());
// static_assert(t.get_value_b());
}
И g cc, и clang согласны, что это должно скомпилироваться, но включение любого закомментированного утверждения stati c делает его недействительным. Например, g cc выдаст следующие сообщения об ошибках:
error: непостоянное условие для stati c assertion
error: значение 't' равно не может использоваться в константном выражении
примечание: 't' не было объявлено 'constexpr'
Это имеет для меня абсолютный смысл и является именно тем, что я бы подумал. Но я действительно не знаю, почему две другие команды c в первую очередь утверждают, что они компилируются. Какой соответствующий абзац из стандарта позволяет это сделать?
В частности, как это формализовано? Есть ли четко определенная разница между просто использованием переменной и фактическим доступом к ее значению во время выполнения (что тогда будет единственной запрещенной вещью в контексте constexpr)?