Почему объявления декомпозиции не могут быть constexpr?
Рассмотрим следующий фрагмент кода для проверки готовящихся объявлений декомпозиции функций C++17 (ранее называвшихся структурированными привязками).
#include <cassert>
#include <utility>
constexpr auto divmod(int n, int d)
{
return std::make_pair(n / d, n % d); // in g++7, also just std::pair{n/d, n%d}
}
int main()
{
constexpr auto [q, r] = divmod(10, 3);
static_assert(q == 3 && r ==1);
}
Это терпит неудачу на g++7-SVN и clang-4.0-SVN с сообщением:
Декларация декомпозиции не может быть объявлена 'constexpr'
Сбросив constexpr
определение и переход к обычному assert()
работает на обоих компиляторах.
Ни в одном документе WG21, посвященном этой функции, не упоминается constexpr
ключевое слово, ни в положительном, ни в отрицательном.
Вопрос: почему нельзя разложить объявления декомпозиции constexpr
? (кроме "потому что Стандарт говорит так").
1 ответ
Вопрос: почему объявления декомпозиции не могут быть constexpr? (кроме "потому что Стандарт говорит так").
Нет другой причины. Стандарт говорит в [dcl.dcl] p8:
Decl-specier-seq должен содержать только спецификатор типа
auto
(7.1.7.4) и cv-квалификаторы.
Это означает, что это не может быть объявлено с constexpr
,
Это было темой комментария Национального органа на CD C++17, см. US-95 в P0488R0:
Комментарий: Нет очевидной причины, по которой объявления декомпозиции не могут быть объявлены как static, thread_local или constexpr.
Предлагаемое изменение: разрешите constexpr, static и thread_local разрешенному набору спецификаторов decl.
Комментарии GB 16 и GB 17 также связаны между собой.
Эти комментарии были отклонены для C++17 после рассмотрения Рабочей группой Evolution на совещании в ноябре 2016 года. Было неясно, что будут означать некоторые классы хранения для объявления структурированной привязки, и как именно изменить спецификацию, чтобы constexpr
(простое включение в грамматику не скажет, что это значит). Был запрошен документ с описанием пространства для дизайна. Должна быть возможность изменить это в будущем, не нарушая никакого кода, но не было времени сделать это для C++17.