В C ++ 17 if constexpr
был представлен; тем не менее, кажется, нет switch constexpr
(увидеть Вот). Это почему? То есть, если компилятор поддерживает if constexpr
Разве это не тривиально, чтобы поддержать switch constexpr
(в худшем случае в виде цепочки if-then-else-if-etc. или несколько if с некоторыми флагами для контроля прохождения)?
if constexpr
в конечном итоге был получен из более вменяемая форма из static if
концепция. Из-за этого происхождения, применяя ту же идею к switch
по-видимому, не был рассмотрен комитетом по стандартам. Так что это, вероятно, основная причина: никто не добавил ее в статью, поскольку это была ограниченная форма синтаксиса, где switch
не было бы смысла.
Что, как говорится, switch
в нем много багажа. Наиболее заметным моментом является автоматическое поведение при падении. Это делает определение его поведения немного проблематичным.
Видите, одна из сил if constexpr
означает, что сторона, не занятая во время компиляции, будет отброшена при определенных условиях. Это важная часть синтаксиса. Итак, гипотетический switch constexpr
можно ожидать, чтобы иметь аналогичные полномочия.
Это гораздо сложнее сделать с прорывом, так как case
блоки не так принципиально различны, как два блока if
заявление. Особенно если у вас есть условный провалиться. Теперь вы можете сделать switch constexpr
не иметь автоматического падения (или падения вообще), так что различные разделы различны. Но затем вы слегка изменили работу синтаксиса; неconstexpr
форма switch
ведет себя иначе, чем constexpr
форма. Это не хорошо.
Да, вы можете сделать это ошибка компиляции, чтобы не ставить break;
заявления между метками.
Обратите внимание, что два основных предложения сопоставления с образцом, P1308 а также p1260, конкретно избежать с помощью switch
вместо того, чтобы придумывать новое ключевое слово. У них обоих constexpr
аспекты, но они совершенно ясно дают понять, что они не являются switch/case
,
Я не авторитетный, но если вы посмотрите на выбор заявления if
имеет четкое разделение между истинными и ложными утверждениями, switch
не делает.
Я предполагаю, что было бы относительно сложнее отбросить неиспользованные части перехода от оценки, тем более что они могут провалиться.
Переопределение switch
как if-else-if
не все так просто, если вы хотите сохранить все его (экзотические) возможности.
Рассмотрим следующий пример из ответ на другой вопрос (об оптимизированном if
ветви).
struct Cat { void meow() { } };
struct Dog { void bark() { } };
template <typename T>
void pet(T x)
{
if(std::is_same<T, Cat>{}){ x.meow(); }
else if(std::is_same<T, Dog>{}){ x.bark(); }
}
pet(Cat{});
pet(Dog{});
Вы не можете повторить это с помощью переключателя, потому что вам нужно, чтобы значения регистра действительно были типами; что-то вроде следующего, что невозможно по понятным причинам.
template <typename T>
void pet(T x)
{
switch (T) {
case Cat:
x.meow();
break;
case Dog:
x.meow();
break;
}
}
Этот пример является своего рода причиной if constexpr
: сравнение типов или других вещей, которые не являются просто набором значений. Так что switch constexpr
не имеет особого смысла для меня. Во всяком случае, ему понадобится другой синтаксис (вроде моего примера), и я не уверен, что это будет полезно. Это, конечно, не нужно.