C++ constexpr的等价三元运算符if?

C++ constexpr的等价三元运算符if?,c++,constexpr,c++17,if-constexpr,C++,Constexpr,C++17,If Constexpr,也许我遗漏了什么,但我找不到任何提示:在C++17中是否有一个与constexpr if等价的constexpr三元运算符 template<typename Mode> class BusAddress { public: explicit constexpr BusAddress(Address device) : mAddress(Mode::write ? (device.mDevice << 1) : (device.mDevice &

也许我遗漏了什么,但我找不到任何提示:在C++17中是否有一个与constexpr if等价的constexpr三元运算符

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;    
};
模板
类总线地址{
公众:
显式constexpr总线地址(地址设备):

mAddress(Mode::write?(device.mDevice否,没有
constexpr
条件运算符。但您可以将整个内容包装在lambda中,并立即对其求值(an):

模板
类总线地址{
公众:
显式constexpr总线地址(地址设备)
:疯狂的{
if constexpr(模式::写入){

return device.mDevice您似乎认为如果constexpr
是一种性能优化,那么它就不是。如果在
?:
子句中放入一个常量表达式,任何值得使用的编译器都会找出它的解析结果并删除该条件。因此,您编写的代码几乎肯定会编译下至单个选项,用于特定的
模式

if constexpr
的主要目的是完全消除另一个分支。也就是说,编译器甚至不检查它在语法上是否有效。这将适用于
if constexpr(is\u default\u constructible\u v)
的情况,如果它为真,则执行
t()
。使用常规的
if
语句,如果
T
不是默认可构造的,
T()
仍然必须是语法有效的代码,即使周围的
if
子句是常量表达式。
如果constexpr
删除了该要求,编译器将丢弃不在其他条件下的语句

对于
?:
,这变得更加复杂,因为表达式的类型基于这两个值的类型。因此,两个表达式都必须是合法表达式,即使其中一个从未计算过。
?:
constepr
形式可能会放弃编译时未采用的替代方法。因此表达式的类型实际上应该仅基于其中一个


这是一种完全不同的东西。

为方便起见,接受的答案也可以转换为模板函数:

#包括
#包括
模板
decltype(auto)constepr_if(Then&&Then,OrElse&&or_else){
如果constexpr(cond_v){
返回std::forward(然后);
}否则{
返回标准::转发(或其他);
}
}
//例子
struct ModeFalse{static constexpr bool write=false;};
struct ModeTrue{static constexpr bool write=true;};
结构A{};
结构B{};
模板
auto&&test=constexpr\u if(A{},B{});
静态断言(std::is_same_v);
静态断言(std::is_same_v);
常数A;
B B;
模板
auto&&test2=constexpr_if(a,b);
静态断言(std::is_same_v);
静态断言(std::is_same_v);

不,没有。但是如果你告诉我们更多关于你想做什么的话,我们可以建议一种解决方法。假设一个三元表达式可以是
constexpr
,那么编译器将在编译时计算它(换句话说,不需要特殊的
constexpr
三元运算符),这难道不好吗@qxz我认为,如果constexpr
真正类似,那么它也具有这样一个属性,即未执行的分支将被丢弃(因此,即使该分支未编译,整个过程也会编译)。刚刚添加了一个小示例解决方法:将三元
if
封装在
constexpr
函数中。然后调用它来初始化类成员。我正在寻找这样一个constexpr
?:
正是因为类型差异:我想移动并构造一个声明为
auto
的局部变量,并使用expres的结果如果constexpr
,我不能使用常规的
,而不将其包装到函数中(或iLife,请参见@Barry的答案)。我更愿意避免这种语法噪音。即使是丢弃的语句也必须在语法上有效,但不必在语义上有效(它们可以做准语法的事情,比如声明不存在的嵌套类型的变量)根据constexpr生成。因此,虽然这不是对发布版本的优化,但在条件中使用constexpr在调试版本中非常有可能是一种优化。这在复杂模板中特别有用,其中存在许多代码路径,但根据模板参数,只有一个是可能的。此类函数在过去已经被开发过当试图调试一个问题时,它是一个沉重的负担,但是使用constexpr可以大大减轻负担,而不必依赖编译器的巧妙优化功能和调试符号信息。这当然不能避免对双方进行评估,但是如果主要问题是它们的类型不同,那么它可能非常方便。是的,我同意。
cons的参数texpr_if
必须格式良好,才能使其与公认的答案相反。
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;    
};