& quot; constexpr if & quot; против & quot; если & quot; с оптимизацией — почему «constexpr» нужно?

В C ++ 1z будет введено «constexpr if» — в случае if будет удалена одна из ветвей в зависимости от условия. Кажется разумным и полезным.

Однако нельзя ли обойтись без ключевого слова constexpr? Я думаю, что во время компиляции, компилятор должен знать, известно ли условие во время компиляции или нет. Если это так, даже самый базовый уровень оптимизации должен удалить ненужную ветвь.

Например (см. В Годболт: https://godbolt.org/g/IpY5y5):

int test() {
const bool condition = true;
if (condition) {
return 0;
} else {
// optimized out even without "constexpr if"return 1;
}
}

Исследователь Godbolt показывает, что даже gcc-4.4.7 с -O0 не скомпилировал «return 1», поэтому он достиг того, что было обещано с constexpr if. Очевидно, что такой старый компилятор не сможет сделать это, когда условие является результатом функции constexpr, но факт остается фактом: современный компилятор знает, является ли условие constexpr или нет, и не нуждается в том, чтобы я говорил это явно.

Итак, вопрос:

Почему «constexpr» нужен в «constexpr if»?

34

Решение

Это легко объяснить на примере. Рассматривать

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{});

вызовет ошибку компиляции (пример wandbox), потому что обе ветви if Заявление должно быть правильно оформлено.

prog.cc:10:40: error: no member named 'bark' in 'Cat'
else if(std::is_same<T, Dog>{}){ x.bark(); }
~ ^
prog.cc:15:5: note: in instantiation of function template specialization 'pet<Cat>' requested here
pet(Cat{});
^
prog.cc:9:35: error: no member named 'meow' in 'Dog'
if(std::is_same<T, Cat>{}){ x.meow(); }
~ ^
prog.cc:16:5: note: in instantiation of function template specialization 'pet<Dog>' requested here
pet(Dog{});
^

изменения pet использовать if constexpr

template <typename T>
void pet(T x)
{
if constexpr(std::is_same<T, Cat>{}){ x.meow(); }
else if constexpr(std::is_same<T, Dog>{}){ x.bark(); }
}

требуется только разбор ветвей — только ветвь, соответствующая условию, должна быть правильно сформирована (пример wandbox).

Фрагмент

pet(Cat{});
pet(Dog{});

скомпилирует и будет работать как положено.

45

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]