Функция constexpr шаблона базового класса в производном классе и получила ошибку

template <typename... Ts>
struct A
{
    template <typename C>
    constexpr auto proc() noexcept { return C{ }; }
    constexpr size_t size() noexcept { return sizeof...(Ts); }
};

template <typename... Ts>
struct B : public A<Ts...>
{
    using base_t = A<Ts...>;

    template <typename... Cs>
    constexpr auto example_prog_1() noexcept
    {
        constexpr size_t tmp = base_t::size();
        // error C2131 : its not constexpr
        return tmp + sizeof...(Cs);
    }

    template <typename... Cs>
    constexpr auto example_prog_0() noexcept
    {
        return example_prog_1<decltype(base_t::template proc<Cs>())...>();
    }
};

int main()
{
    B<int, int, int, int> obj0 { };
    constexpr size_t result0 = obj0.example_prog_0<char, char, char, char>();
}

это не работает. я получил ошибку C2131: Выражение не равно константе.

    template <typename... Cs>
    constexpr auto example_prog_1() noexcept
    {
        B dup{ };
        constexpr size_t tmp = dup.size();
        // error none  : its fine
        return tmp + sizeof...(Cs);
    }

но сделать копию - это нормально.

он также работает, когда добавляется «это автоматическое сам» и используется.

может кто-нибудь сказать мне, почему? (msvc/std: c++ последняя версия)

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
85
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

base_t::size() это this->base_t::size().

Вам не разрешено разыменовывать указатели, которые были созданы вне константного выражения (или которые можно использовать в самих константных выражениях) в константном выражении. Это будет «чтение значения указателя», о котором компилятор не знает во время компиляции.

Это была формулировка до P2280R4 , которую MSVC не реализует. Эта статья и этот вопрос ( Почему ссылочный параметр в функции constexpr не является постоянным выражением?) Ответы более подробно объясняют, почему это произошло раньше.

Если у вас есть что-то, что не является указателем или ссылкой (например, по значению this auto self или B dup {};), это больше не применяется. Это постоянное выражение для вызова функции-члена, поскольку у вас нет доступа к объекту.

Самое простое решение — создать функцию sizestatic. Многие из ваших функций могут быть static.

Другие вопросы по теме

Достаточно ли времени жизни локальной лямбды в качестве обработчика завершения для co_spawn, т.е. функции с functor&&?
Использование std::unique_ptr с выровненным типом приводит к предупреждению компилятора
Ошибка возврата массива из функции consteval
Каков ожидаемый результат при объявлении локальной автоматической функции?
Как суммировать std::range?
Как распечатать неструктурные результаты функций constexpr во время компиляции с помощью clang++?
Почему take(n), используемый в istream_view, приводит к пропуску следующего токена в C++20?
Почему объявление функции глобальной области со встроенным типом arg должно быть видимым перед неквалифицированным вызовом этого имени с аргументом типа шаблона?
Есть ли способ отсортировать одну переменную-член в коллекции структур с помощью стандартной библиотеки C++?
Не могу создать std::ranges::subrange с помощью моего итератора

Похожие вопросы