web-dev-qa-db-ja.com

constexprの同等の三項演算子if?

多分私は何かを見逃しましたが、ヒントは見つかりません:constexpr-ifと同等のC++ 17の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;    
};
32
wimalopaan

いいえ、constexepr条件演算子はありません。しかし、全体をラムダでラップしてすぐに評価することもできます(an [〜#〜] 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;    
};

それはこれまでで最もセクシーなコードではないかもしれませんが、それは仕事を成し遂げます。ラムダは N4487 および P017 の時点で可能な限りデフォルトでconstexprであることに注意してください。

14
Barry

_if constexpr_はパフォーマンスの最適化であるという信念の下で行動しているようです。それはではないです。定数式を_?:_句に入れると、使用する価値のあるコンパイラは、それが何に解決されるかを理解し、条件を削除します。したがって、記述したコードは、特定のModeの場合、ほぼ確実に単一のオプションにコンパイルされます。

_if constexpr_の主な目的は、他のブランチを完全に排除することです。つまり、コンパイラーは構文的にvalidであるかどうかを確認することさえしません。これは、あなたがif constexpr(is_default_constructible_v<T>)である場合に当てはまり、それがtrueの場合はT()を実行します。通常のifステートメントでは、Tがデフォルトで構成可能でない場合、if句が周囲にある場合でも、T()は構文的に有効なコードである必要があります定数式です。 _if constexpr_はその要件を削除します。コンパイラーは、他の条件にないステートメントを破棄します。

式のタイプは2つの値のタイプに基づいているため、これは_?:_ではさらに複雑になります。そのため、どちらか一方が評価されない場合でも、両方の式は正しい式である必要があります。 _?:_のconstexpr形式は、コンパイル時に取得されない代替案をおそらく破棄します。したがって、式のタイプは実際にはそのうちの1つにのみ基づいている必要があります。

それは非常に異なる種類のことです。

14
Nicol Bolas