也许我错过了什么,但我找不到任何提示: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;
};
答案 0 :(得分:12)
您似乎认为if constexpr
是性能优化。它不是。如果在?:
子句中放置一个常量表达式,任何值得使用的编译器都会找出它解析的内容并删除条件。因此,您编写的代码几乎肯定会编译为单个选项,对于特定的Mode
。
if constexpr
的主要目的是完全消除另一个分支。也就是说,编译器甚至不检查它是否在语法上有效。这适用于您if constexpr(is_default_constructible_v<T>)
的内容,如果属实,则执行T()
。使用常规if
语句,如果T
不是默认可构造的,则T()
仍然必须是语法上有效的代码,即使周围的if
子句是常量表达式。 if constexpr
删除了该要求;编译器将丢弃不属于其他条件的语句。
?:
这变得更加复杂,因为表达式的类型基于两个值的类型。因此,两个表达式都需要是合法的表达式,即使其中一个表达式从未被评估过。一个constexpr
形式的?:
可能会丢弃在编译时未采用的替代方法。因此,表达式的类型应该只基于其中一个。
这是一种非常不同的事情。
答案 1 :(得分:0)
为方便起见,也可以将接受的答案翻译成模板函数:
#include <type_traits>
#include <utility>
template <bool cond_v, typename Then, typename OrElse>
decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) {
if constexpr (cond_v) {
return std::forward<Then>(then);
} else {
return std::forward<OrElse>(or_else);
}
}
// examples
struct ModeFalse { static constexpr bool write = false; };
struct ModeTrue { static constexpr bool write = true; };
struct A {};
struct B {};
template <typename Mode>
auto&& test = constexpr_if<Mode::write>(A{}, B{});
static_assert(std::is_same_v<A&&, decltype(test<ModeTrue>)>);
static_assert(std::is_same_v<B&&, decltype(test<ModeFalse>)>);
const A a;
B b;
template <typename Mode>
auto&& test2 = constexpr_if<Mode::write>(a, b);
static_assert(std::is_same_v<const A&, decltype(test2<ModeTrue>)>);
static_assert(std::is_same_v<B&, decltype(test2<ModeFalse>)>);