Может быть, я что-то пропустил, но не могу найти подсказки: есть ли в C ++ 17 троичный оператор constexpr, эквивалентный constexpr-if?
template<typename Mode>
class BusAddress {
public:
explicit constexpr BusAddress(Address device) :
mAddress(Mode::write ? (device.mDevice << 1) : (device.mDevice << 1) | 0x01) {}
private:
uint8_t mAddress = 0;
};
Вы, кажется, действуете в убеждении, что if constexpr
это оптимизация производительности. Это не. Если вы поместите постоянное выражение в ?:
В этом случае любой компилятор, который стоит использовать, выяснит, к чему он приводит, и удалит условие. Таким образом, код, который вы написали, почти наверняка скомпилируется в один вариант для определенного Mode
,
Основная цель if constexpr
это полностью исключить другую ветку. То есть компилятор даже не проверяет, синтаксически ли он действительный. Это было бы для чего-то, где вы if constexpr(is_default_constructible_v<T>)
и если это правда, вы делаете T()
, С регулярным if
заявление, если T
не является конструируемым по умолчанию, T()
все равно должен быть синтаксически действительный код, даже если окружающий if
предложение является константным выражением. if constexpr
устраняет это требование; компилятор будет отбрасывать операторы, которые не находятся в другом условии.
Это становится еще сложнее для ?:
, потому что тип выражения основан на типах двух значений. Таким образом, оба выражения должны быть допустимыми, даже если одно из них никогда не оценивается. constexpr
форма ?:
предположительно отбросил бы альтернативу, которая не берется во время компиляции. И поэтому тип выражения должен действительно основываться только на одном из них.
Это совсем другая вещь.
Нет, нет constexepr
условный оператор. Но вы можете обернуть все это в лямбду и сразу же оценить ее ( IIFE):
template<typename Mode>
class BusAddress {
public:
explicit constexpr BusAddress(Address device)
: mAddress([&]{
if constexpr (Mode::write) {
return device.mDevice << 1;
}
else {
return (device.mDevice << 1) | 0x01;
}
}())
{ }
private:
uint8_t mAddress = 0;
};
Возможно, это не самый сексуальный код, но он выполняет свою работу. Обратите внимание, что лямбды constexpr
по умолчанию, где это возможно, начиная с N4487 а также P0170.