Избегайте оценки ветки if-constexpr, которая не занята

Следующий код не компилируется с ошибкой no member named 'foo' in 'B', несмотря на то, что это проблема только в контексте, который следует отбросить во время компиляции.

#include <type_traits>

struct A {
    int foo() {
        return 1;
    }
};

struct B {
    int bar() {
        return 2;
    }
};

static constexpr bool TEST = false;
using T = std::conditional_t<TEST, A, B>;

int main() {
    T t{};
    if constexpr (TEST) {
        return t.foo();
    } else {
        return t.bar();
    }
}

Что я могу сделать, чтобы включить такой код? Если бы я заменил constexpr макросами препроцессора, это, скорее всего, сработало бы нормально, не так ли?

if constexpr работает только в шаблонах функций. main не является шаблоном функции
NathanOliver 02.05.2024 02:16

Операторы можно отбросить, только если они находятся в зависимом контексте. Поместите это в шаблон функции, приняв тип T, и все заработает.

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

Ответы 1

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

https://en.cppreference.com/w/cpp/language/if рассказывает о вашей ситуации:

Вне шаблона отброшенный оператор полностью проверяется

Это говорит о том, что вы можете вставить его в шаблон, чтобы он работал:

template <typename U=T> int myMain()
{
    U t{};
    if constexpr (TEST) {
        return t.foo();
    } else {
        return t.bar();
    }
}

int main() {
    return myMain();
}

Примечание. На самом деле все должно зависеть от параметра шаблона; если вы просто сохраните T t{};, эта переменная на самом деле не является шаблонной, и компилятор снова просто снова будет жаловаться. Итак, мне пришлось предложить небольшой обходной путь — с точки зрения компилятора я мог передать любой U, поэтому он понятия не имеет, каким будет t, и поэтому он будет работать.

cppreference на самом деле объясняет это как

Если оператор constexpr if появляется внутри шаблонной сущности и если после создания экземпляра условие не зависит от значения, отброшенный оператор не создается при создании экземпляра включающего шаблона.

Однако их объяснение «зависимости от ценности» написано на каком-то языке, который, кажется, использует английские слова, но не передает много смысла. Итак, я приведу свое интуитивное объяснение плюс часть «отброшенный оператор не создается» из приведенной выше цитаты и пойду спать без головной боли.

поведение, отличающееся в зависимости от того, относится ли оно к параметру шаблона функции, является неожиданным. Мне любопытно узнать, почему было бы желательно оценить не выбранную ветку, но, тем не менее, это именно то, что я искал. Спасибо!

Keltek 02.05.2024 02:55

@keltek да, меня это тоже в какой-то момент поразило. Не исключено, что это еще одна уступка производителям компиляторов. Фактически, функционально if constexpr вне шаблонов ощущается почти как обычно ìf за исключением того, что код не создается даже без оптимизации — при оптимизации и постоянном условии в одной из веток также будет удален код, и мы также просто "проверь"...

Christian Stieber 02.05.2024 03:15

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