"If constexpr" полезен вне шаблонов?

Я пытаюсь понять if constexpr от корки до корки.

Я понимаю, что если if constexpr(expr) используется в шаблоне, и expr зависит от параметра шаблона, то во время реализации только один из then/else ветви будут созданы, остальные будут отброшены.

У меня есть два вопроса:

  • Правда ли, что если expr не зависит от параметра шаблона, то нет ветвей if constexpr(expr) будет отброшен? Если да, то где стандарт так говорит? Я не вижу, где в стандарте есть исключение, что отказ происходит только тогда, когда expr зависит.
  • Является if constexpr полезно вне шаблонов? Если да, каковы варианты использования этого? Можете ли вы привести несколько примеров, чтобы понять его полезность?

1 ответ

Решение

Правда ли, что если expr не зависит от параметра шаблона, то нет ветвей if constexpr(expr) будет отброшен? Если да, то где стандарт так говорит? [...]

Да это правда. Вы ищете [stmt.if] / 2. Конкретно эта часть:

[…] Во время создания экземпляра вмещающего шаблонного объекта, если условие не зависит от значения после его создания, отброшенное подкрепление (если оно есть) не создается. [...]

Лучший пример, который я мог бы найти для случая, когда вы оказались бы в зависимости от значения после создания экземпляра, это пример, приведенный cppreference.com:

template<class T> void g() {
    auto lm = [](auto p) {
        if constexpr (sizeof(T) == 1 && sizeof p == 1) {
           // this condition remains value-dependent after instantiation of g<T>
        }
    };
}

Является if constexpr полезно вне шаблонов? Если да, можете ли вы привести несколько примеров, чтобы понять его полезность?

В то время как все ветви будут созданы, когда if constexpr не отображается внутри шаблона, [basic.def.odr] / 10 по- прежнему применяется:

Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе с помощью odr, кроме исключенного оператора; [...]

Акцент мой. Это фактически означает, что использование odr сущности в отброшенном выражении не учитывается. Например:

void blub();

constexpr bool use_blub = false;

void f()
{
    if constexpr (use_blub)
    {
        blub();
    }
}

Призыв к blub() не потребует, чтобы ваша программа имела определение blub() если условие ложно. Используя нормальный if программа все равно должна будет дать определение blub() где-то, даже если он никогда не используется. Так что вы могли бы, например, использовать if constexpr переключаться между вызовом некоторой библиотечной функции и вызовом некоторой резервной реализации, в зависимости от того, доступна ли библиотека (и не связана ли она). Кроме того, гипотетически, компилятор может не предупреждать о недоступном коде, если он недоступен из-за if constexpr как это было бы потенциально с нормальным if, Я не мог придумать пример этого с использованием какого-либо фактического компилятора, однако...

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