Почему функция constexpr для ссылки не является constexpr? - PullRequest
0 голосов
/ 10 января 2019

Рассмотрим следующую функцию:

template <size_t S1, size_t S2>
auto concatenate(std::array<uint8_t, S1> &data1, std::array<uint8_t, S2> &data2) {
    std::array<uint8_t, data1.size() + data2.size()> result;

    auto iter = std::copy(data1.begin(), data1.end(), result.begin());
    std::copy(data2.begin(), data2.end(), iter);

    return result;
}

int main()
{
    std::array<uint8_t, 1> data1{ 0x00 };
    std::array<uint8_t, 1> data2{ 0xFF };

    auto result = concatenate(data1, data2);
    return 0;
}

При компиляции с использованием clang 6.0, с использованием -std = c ++ 17, эта функция не компилируется, поскольку функция-член размера в массиве не является constexpr из-за того, что она является ссылкой. Сообщение об ошибке таково:

ошибка: нетипизированный аргумент шаблона не является константным выражением

Когда параметры не ссылки, код работает как ожидалось.

Интересно, почему это так, поскольку size () на самом деле возвращает параметр шаблона, вряд ли он может быть более постоянным. Независимо от того, является ли параметр ссылкой или нет, не имеет значения.

Я знаю, что могу, конечно, использовать параметры шаблона S1 и S2, эта функция является лишь краткой иллюстрацией проблемы.

Есть ли что-нибудь в стандарте? Я был очень удивлен, получив из этого ошибку компиляции.

Ответы [ 3 ]

0 голосов
/ 10 января 2019

Об этой проблеме сообщалось об ошибке для clang под названием: Clang не позволяет использовать преобразование типа constexpr в аргументе шаблона не-типа .

Обсуждение в нем указывает, что это на самом деле не ошибка.

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

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

Приведенная выше цитата взята из [expr.const] /2.11 черновика n4659 с добавлением акцента.

0 голосов
/ 10 января 2019

К сожалению, стандарт гласит, что в выражении доступа к члену класса Выражение постфикса перед точкой или стрелкой вычисляется; 63 [expr.ref] / 1 . Постфиксное выражение: a в a.b. Примечание действительно интересно, потому что это именно тот случай:

63) Если вычисляется выражение доступа к члену класса, оценка подвыражения происходит, даже если в результате нет необходимости определять значение всего выражения постфикса, например, если id-выражение обозначает статический член.

Таким образом, data оценивается, даже если в этом нет необходимости, и к нему применяется правило для константного выражения.

0 голосов
/ 10 января 2019

Потому что вы оценили ссылку. От [expr.const] / 4 :

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

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

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

Вы можете просто использовать S1 + S2 вместо этого здесь.

...