2

constexpr とマークされた関数は、不変の純粋な関数であると想定されています。「std::max() and std::min() not constexpr」投稿から、const 参照入力を出力として再チャネル化することはできません。これには、パラメーターに永続性が必要になるためです。constしかし、再チャネル化しない限り、パラメータを -reference で取得できますか?

// Is this still constexpr?
// (Assuming that std::complex is constexpr-safe, as it's supposed to be.)
constexpr
int  MySum( std::complex<double> const &a, std::complex<double> const &b )
{ return static_cast<int>( a.real() + b.real() ); }

逆に、-enabled 型のサブオブジェクトへの const 参照を返すことはできますconstexprか?

template <typename T>
class MyComplex
{
    T  c_[ 2 ];
public:
    constexpr MyComplex( T r = T(), T i = T() )
    : c_{ r, i }
    {}

    // Is this actually constexpr?
    constexpr T const &  operator[]( unsigned l ) //const
    { return c_[ l ]; }

    // Can't be constexpr
    T &  operator[]( unsigned l )  { return c_[ l ]; }
};

それとも、サブオブジェクトの戻り値でさえも値渡しである必要がありますか?

(これが基本的なものである場合は申し訳ありませんが、実際に決定的ではなく、この時点で私が見つけたものはすべてダンスです。)

4

2 に答える 2

4

constexpr標準は、関数で何が許可されているかについて非常に明確です。

§7.1.5 [dcl.constexpr] p3

関数の定義はconstexpr、次の制約を満たさなければなりません。

  • [...]
  • その戻り型はリテラル型でなければなりません。
  • そのパラメータの型はそれぞれリテラル型でなければなりません。
  • [...]

§3.9 [basic.types] p10

次の場合、型はリテラル型です。

  • スカラー型。また
  • 参照型; また
  • 次のすべてのプロパティを持つクラス タイプ (条項 9):
  • 自明なデストラクタがあり、
    • 非静的データ メンバー (存在する場合) のブレースまたはイコール初期化子内のすべてのコンストラクター呼び出しと完全式は、定数式 (5.19) です。
    • 集約型 (8.5.1) であるか、またはコピーまたは移動コンストラクターではない少なくとも 1 つの constexpr コンストラクターまたはコンストラクター テンプレートを持ち、かつ
    • すべての非静的データ メンバーとリテラル型の基本クラスがあります。また
  • リテラル型の配列。

そのため、はい、非定数への参照であっても、参照パラメーターを使用できます。関数のパラメーターはconstexpr別の方法で制限されます。完全で網羅的なリストは、 の下にあり§5.19 [expr.const] p2ます。constexpr以下は、宣言された関数がconstexprもはやそうではない理由の抜粋です。

conditional-expressionは、評価される可能性のある部分式 (3.2) として次のいずれかが含まれていない限り、コア定数ですが、評価されない論理 AND (5.14)、論理 OR (5.15)、および条件付き (5.16) 演算の部分式は含まれません。は考慮されません [注:オーバーロードされた演算子は関数を呼び出します。—終わりのメモ]:

(論理演算子に関する最後のビットは、その未評価部分 (短絡評価による) が、関数が本当に であるかどうかを決定する操作の一部ではないことを意味しconstexprます。)

  • [...]
  • 動的キャスト (5.2.7);
  • ( 5.2.10 reinterpret_cast);
  • 疑似デストラクタ呼び出し (5.2.4);
  • インクリメントまたはデクリメント操作 (5.2.6、5.3.2);
  • オペランドが多相クラス型である typeid 式 (5.2.8)。
  • 新しい式( 5.3.4 );
  • 削除式( 5.3.5 );
  • 両方のオペランドがポインターである減算 (5.7)。
  • 結果が指定されていない関係 (5.9) または等価 (5.10) 演算子。
  • 割り当てまたは複合割り当て(5.17); また
  • [...]
于 2012-02-13T04:27:59.890 に答える
1

コア イシュー 1454の解決により、Johannes がstd::max の質問に対する回答で参照しているルールが変更されました。その問題の現在の解決策 (g++ と clang の両方で実装されています) では、constexpr関数は、計算できる任意の左辺値を参照によって返すことができます。

于 2012-03-02T06:18:36.360 に答える