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