Выражение не приводило к константе двухуровневых функций constexpr (ошибка компилятора?) - PullRequest
1 голос
/ 04 июля 2019

У меня есть следующий код:

#include <iostream>
template<int I>
class A
{
public:
    inline constexpr static int size() { return I; }
};

template<typename T>
inline constexpr auto size(const T& arg) noexcept -> decltype(arg.size())
{
    return arg.size();
}

template<typename T>
inline constexpr void twoLevel(const T& arg) noexcept
{
    static_assert(size(arg) > 0);
}

int main()
{
    A<5> a;
    static_assert(size(a)>0); //this works
    twoLevel(a); // this does not
    return 0;
}

, который не компилируется в msvc с ошибкой expression did not evaluate to a constant, но работает с gcc. Это gcc принимает что-то, что является неопределенным поведением? Или это ошибка компилятора со стороны msvc? Вот демо: Код Годбола

1 Ответ

1 голос
/ 04 июля 2019

С [expr.const] / 4 :

Выражение e является выражением основной константы , если только оценка e, следуя правилам абстрактной машины, оценил бы одно из следующих выражений:

  • [...]
  • id-выражение , которое относится кпеременная или член данных ссылочного типа, если только ссылка не имеет предшествующей инициализации и либо
    • ее можно использовать в константных выражениях, либо
    • ее время жизни началось в пределах оценки e;
  • [...]

In:

static_assert(size(arg) > 0);

У нас есть id-выражение , котороессылается на переменную ссылочного типа, и ссылка не имеет предшествующей инициализации, поэтому у нас нет константного выражения.

Я думаю, что это так:

static_assert(size(a) > 0);

работает из-за "предшествующей"«инициализация» - мы вводим постоянную оценку, напрямую связывая ссылку arg с переменной a, wздесь, в другом случае, мы привязываем ссылку к другой ссылке.

Оба должны работать, если вы берете значение.

...