wim*_*aan 27 c++ constexpr c++17 if-constexpr
也许我错过了一些东西,但我找不到任何提示: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;
};
Run Code Online (Sandbox Code Playgroud)
Bar*_*rry 17
不,没有constexepr条件运算符.但你可以将整个东西包裹在lambda中并立即评估它(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;
};
Run Code Online (Sandbox Code Playgroud)
它可能不是有史以来最性感的代码,但它完成了工作.请注意,constexpr从N4487和P0170开始,默认情况下默认使用lambdas .
Nic*_*las 14
你似乎是在if constexpr一种性能优化的信念下行事.事实并非如此.如果在?:子句中放置一个常量表达式,任何值得使用的编译器都将确定它解析的内容并删除条件.所以你编写的代码几乎肯定会编译成一个特定的选项Mode.
其主要目的if constexpr是完全消除其他分支.也就是说,编译器甚至不检查它是否在语法上有效.这适用于if constexpr(is_default_constructible_v<T>)你所做的事情,如果是真的,那就是你做的事情T().使用常规if语句,如果T不是默认构造,T()即使around if子句是常量表达式,仍然必须是语法上有效的代码.if constexpr删除该要求; 编译器将丢弃不在其他条件下的语句.
这变得更加复杂?:,因为表达式的类型基于两个值的类型.因此,两个表达式都需要是合法的表达式,即使其中一个表达式从未被评估过.一种constexpr形式?:可能会丢弃在编译时未采用的替代方案.因此表达式的类型应该只基于其中一个.
那是一种非常不同的事情.