Если есть инструкция constexpr if, почему бы и другие инструкции constexpr тоже?
Есть ли какая-либо причина только if constexpr
для включения в С++ 17?
Я мог бы сделать это:
template <int N>
constexpr int fib() {
if constexpr (N == 1 || N == 2) {
return 1;
} else {
return fib<N - 1>() + fib<N - 2>();
}
}
Почему комитет С++ не рассмотрел switch constexpr
тоже?
template <int N>
constexpr int fib() {
switch constexpr (N) {
case 1:
case 2: return 1;
default: return fib<N - 1>() + fib<N - 2>();
}
}
Он выглядел намного круче с помощью switch constexpr
Или даже преждевременный цикл цикла компиляции отключается с помощью for constexpr
/while constexpr
без использования функции замены шаблона/рекурсивного шаблона:
constexpr void printFoo() {
for constexpr (auto i = 0; i < 10; i++) {
cout << fib<i>() << endl;
}
}
Будут ли они включены в С++ 20/будущие версии С++?
Ответы
Ответ 1
if constexpr
был предложен относительно близко к завершению С++ 17.
Украшения (например, switch
) могли отложить его включение.
Необычные, такие как принудительное разворот цикла, несомненно, имели бы.
Требуется реальная работа по изменению стандарта С++. Вы должны реализовать его самостоятельно в компиляторе как доказательство того, что это можно сделать, убедить других авторов компилятора, что это должно быть легко или стоит усилий, выработать, как это должно быть сформулировано в стандарте, чтобы быть ясным и однозначным, убедить других членов комитет, что ваше изменение не просто круто на языке и т.д.
Для этого не требуется причина для не. Все происходит не всегда. Улучшение С++ - это не естественный процесс, который происходит, если кто-то не останавливает его,
Tl; dr: потому что вы не предлагали его и мужа его через стандартизацию. Начните сегодня, и это возможно в С++ 20. "Я не достоин" предлагать, это не оправдание: это работа, которую нужно делать, а не какая-то благодарность за то, что она была потрясающей. Выполняя эту работу, становится потрясающе. "Я ленивый" - оправдание, с которым я знаком.
Ответ 2
Комитет по стандартам С++ вообще не добавляет новые функции только потому, что они "выглядят круто". Каждая новая функция добавляется только после подачи статьи, в которой предлагается тщательно обработанный закон, который точно определяет синтаксис и семантику функции, который часто проходит через несколько ревизий, поскольку все последствия хэшируются экспертами.
Это создает естественный барьер для добавления новых возможностей: если функциональность, которую он добавит к языку, недостаточно для того, чтобы сделать этот изнурительный опыт стоящим, тогда никто не станет предлагать его формально.
if constexpr
является ценным дополнением к языку (попробуйте переписать код, чтобы не использовать его, и вы поймете, почему), и было не так сложно указать: если условие истинно, то второе подзадачу отбрасывается, в противном случае первая субстанция будет отброшена.
Напротив, switch constexpr
будет создавать гораздо большие трудности в формулировке из-за больших сложностей операторов switch
. (Однако вы можете попробовать.) Например, у вас есть естественное ожидание того, как это должно работать:
switch constexpr (x) {
case 1:
bar<x>();
if constexpr(y) { break; }
case 2:
baz<x>();
}
а именно, что если x
равно 1 и y
истинно, то baz<x>
не создается, но если x
равно 1, а y
- false, то baz<x>
создается. Если вы хотите использовать эту семантику, вам нужно выяснить стандарт, который должен будет указать эффективную процедуру для определения того, какие именно инструкции отбрасывать (имейте в виду, что эти if
и switch
es могут быть произвольно вложены). Если вы не хотите эту семантику, ваш switch constexpr
, вероятно, не будет более мощным, чем пучок if constexpr
, но будет иметь ограничения по сравнению с обычным оператором switch
.
Эти трудности еще больше возрастают с помощью for constexpr
. Теперь это может стоить того. Но кто-то должен приложить усилия.
Ответ 3
Не ответ, но слишком длинный для комментария. Вы можете развернуть цикл цикла компиляции в компиляторе Intel (R) с помощью #pragma unroll
.
void bar();
constexpr void foo() {
#pragma unroll(10)
for (auto i = 0; i < 10; i++) {
bar();
}
}
void baz()
{
foo();
}
Живой пример в Godbolt, чтобы доказать разворот.