5

予想通り、問題なく以下のサンプルをコンパイルできます

// first_sample.cpp
struct sample_struct
{
    constexpr int 
    sample_method() 
    { return 5; }
};

int main() 
{
    sample_struct sample_object;
    constexpr int sample_variable = sample_object.sample_method();
    return 0;
}

しかし、次の理由で次のサンプルをコンパイルできません

'this' は定数式ではありません

// second_sample.cpp
struct sample_struct
{
    constexpr int 
    sample_method_first() 
    { return 5; }

    void 
    sample_method_second() 
    {   constexpr int sample_variable = sample_method_first(); 
        /* Do something with sample_variable */ }
};

int main() 
{ return 0; }

私はこの「問題」を解決する方法をすでに知っているので、解決策を求めていません。別のメソッド内で同じ constexpr メソッドを呼び出すことが許可されていないのに、非 constexpr オブジェクトから constexpr メソッドを呼び出すことが許可されている理由の合理的な説明を求めています(非 constexpr 'this' から)。

4

2 に答える 2

0

constexpr関数は、定数式であるかどうかに関係なく、任意のコンテキストで呼び出すことができます。(そして、あなたsample_method_secondはそうではありませんconstexpr。) しかし、constexprオブジェクトはコンパイル時に評価されなければなりません。

つまり、コンパイル時に結果を取得するためにsample_method_secondコンパイラに使用するように依頼することです。明らかにそれは不可能です。thissample_method_first

違いは、最初の例では、 のスコープにより、コンパイラがonmainのメソッドを呼び出すことができることです。しかし、1 つのオブジェクトの値を評価できることは、プログラム内の潜在的なすべてのオブジェクトに拡張されるわけではありません。sample_objectsample_method_second

解決策 (まあ、usingからsample_method_first独立させることは別として) はas として宣言しないことです。を必要とする方法で使用している場合、最終的なプログラムで 1 つのメンバー関数が実際には複数の (潜在的に無限の) 実装を必要とするため、設計に欠陥があります。thisstaticsample_variableconstexprconstexpr

正当なconstexpr変数の潜在的な異なる値ごとに、新しいテンプレートのインスタンス化、異なる編成の が生成されるswitchか、static_assert. 実行時にさかのぼってやってみてください!


最初のケースが許可される理由については、次のとおりです。

sample_struct sample_object;
constexpr int sample_variable = sample_object.sample_method();

ここで起こっているのはconstexpr関数呼び出しであり、そのルールは除外します

— リテラルクラスの constexpr コンストラクター以外の関数の呼び出し、constexpr 関数、または自明なデストラクタの暗黙の呼び出し (12.4)

constexpr関数の内部を評価するため、または関数の結果を使用するために何かが定数である必要がある場合、左辺値などの他のルールのいずれかに従って評価が失敗するため、オブジェクトがそうである必要はありません。右辺値への変換。sample_method実際に何かにアクセスするように変更することはできません。変更すると、sample_object宣言されていない 、または の値を直接constexpr使用しようとすると、そのアドレスが一定ではないというエラーが表示されます。this

于 2013-07-05T03:49:02.727 に答える