Вопрос или проблема
При синтаксической проверке доступа по подписке с помощью расширения пакета параметров я ожидал, что следующий код будет работать без ошибок. Однако MSVC отклоняет как синтаксис ограничения в секции requires, так и последнюю ассерцию.
template<typename T, typename... Ts>
concept c = requires(T t, Ts... ts) {
{ t[ts...] } noexcept; // clang ok, gcc ok, msvc нет
};
static_assert(not c<int[]>); // все ок
static_assert(not c<int[], int, int>); // все ок
static_assert(c<int[], int>); // clang ok, gcc ok, msvc нет
Является ли это просто багом компилятора MSVC? Какое правило в стандарте C++23 определяет этот код как законный?
Сообщение об ошибке MSVC:
<source>(3): ошибка C2760: синтаксическая ошибка: 'noexcept' здесь была неожиданной; ожидалось ';'
<source>(3): ошибка C2760: синтаксическая ошибка: ']' здесь была неожиданной; ожидалось '}'
<source>(8): ошибка C2607: статическая проверка не удалась
<source>(8): примечание: концепция 'c<int[],int>' оценена как ложная
Ответ или решение
Ваш вопрос касается использования оператора подстановки и расширения параметрических пакетов в C++23, в частности в контексте концептов. Давайте разберемся с проблемой, которую вы описываете.
Проблема
Вы пытаетесь использовать оператор подстановки в контексте концепта с использованием параметрических пакетов. Ваш код имеет две основные части:
- Определение концепта
c
, который проверяет, можно ли выполнить оператор подстановкиt[ts...]
с типомT
и членами из пакетаTs
. - Набор статических утверждений для проверки, действительно ли концепт
c
выполняется для различных комбинаций типов.
Вы отметили, что MSVC не проходит компиляцию из-за различных синтаксических ошибок, в то время как Clang и GCC обрабатывают этот код корректно.
Стандарты C++
Процитируем некоторые специальные моменты из стандарта C++23:
-
Правила для
requires
и концептов — согласно C++20 (и C++23), синтаксис использованияrequires
в концептах позволяет проверять выражения на корректность выполнения. Синтаксис{ t[ts...] } noexcept;
должен считаться допустимым, так как он используется для проверки на корректность выполнения, включая определение, выбросит ли оно исключение или нет. -
Служебные элементы синтаксиса и семантики — вызов
operator[]
с использованием параметрического пакетаts...
должен работать, еслиT
поддерживает такую операцию. Ваша конструкция предполагает, что кt
можно применить оператор подстановки с несколькими индексами, что в принципе возможно для массивов и контейнеров.
Ошибки компилятора MSVC
Судя по сообщениям об ошибках, ошибка происходит из-за того, что MSVC неправильно интерпретирует синтаксис в строке noexcept;
. В C++23 допускается использование noexcept
в данном контексте, и это должно работать. Ошибка expected ';'
указывает на то, что компилятор ищет завершение выражения, в то время как он не может правильно проанализировать выражение.
Почему это может быть ошибкой компилятора
Таким образом, возникает вопрос, является ли проблема с MSVC ошибкой компилятора. Вероятно, что реализация в MSVC не полностью соответствует стандарту C++23 в случае работы с концептами и выражениями, использующими суммирующие пакеты. Также возможно, что в конкретной версии компилятора, которую вы используете, не реализованы все новшества стандарта.
Выводы
-
Ваш код выглядит корректно с точки зрения стандарта C++23, и его ошибки, возникающие в MSVC, можно считать потенциальной проблемой компилятора.
-
Рекомендуется проверить текущую версию компилятора MSVC и его совместимость со стандартом C++23. Возможно, стоит рассмотреть обновление до последней версии, где данные проблемы могут быть исправлены.
-
Если проблема сохраняется, вы можете рассмотреть возможность подачи отчета о баге в Microsoft, чтобы разработчики могли исправить эту несоответствие в будущих обновлениях компилятора.
Надеюсь, эта информация поможет вам разобраться с вашей проблемой.