"If constexpr" полезен вне шаблонов? - PullRequest
0 голосов
/ 03 декабря 2018

Я пытаюсь полностью понять if constexpr.

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

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

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

1 Ответ

0 голосов
/ 03 декабря 2018

Правда ли, что если 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.Я не мог придумать пример этого с использованием какого-либо фактического компилятора, однако ...

...