2013-06-08 12 views
11

constexprの機能は、単にreturn文で構成する必要がありますし、すべての引数はコンパイル時に知られている必要があります。constexpr - なぜreturn文ですか?

// constexpr functions use recursion rather than iteration 
constexpr int factorial(int n) 
{ 
    return n <= 1 ? 1 : (n * factorial(n-1)); 
} 

理由だけではなく、return文?どうしてこれが間違っているの?

// constexpr functions use recursion rather than iteration 
constexpr int factorial(int n) 
{ 
    int a = 222; //another variable 
    return n <= 1 ? 1 : (n * factorial(n-1)); 
} 
+7

私はそれがコンパイラ実装のために簡単に保つことができると考えています。 – juanchopanza

+10

スタンダードはそうそう言います。より一般的な関数を許可すると、コンパイラライターの人生はかなり複雑になります(とにかく、C++ 14ではこれらの制限の一部が解消されます)。 –

+3

変数を許可すると、他の多くの(複雑な)制限が追加されることになります。だから彼らは彼らの紹介のためにそれを簡単に保ちました。とにかく(例えば、他のものから 'constexpr'関数を呼び出す) – Dave

答えて

6

これは、Andy Prowl氏の言うとおり、実装を簡略化します。それはおそらく "なぜ"と答えますが、それがどういうことを言っているのでしょうか。

戻り値のみを持つ関数、より具体的にはローカル変数を持たない関数は、コンパイラにとって特別な状況です。この関数は単一の式で構成されています。関数のASTは単一のルートのみを持つ必要があります。この変数がないということは、この式が処理するために本格的な仮想マシンなしで評価できることを意味します。単純なツリー式評価ツールを使用できます。いろいろな理由から、コンパイラはおそらくすでにそのような評価子を持っているか、比較的簡単に作成することができます(ツリー簡略化のパスになります)。

式内でconstexprのみが使用されていることもわかります。これにより、たとえ関数呼び出しであっても、関数ASTの各頂点が同じプロパティを持つことが保証されます。 constexpr機構全体はconstフォールディングの一般化された形式です。また、コンパイラのこの高レベルでは必ずしも実行されるわけではありませんが、完全なVMと比較して莫大な労力をかけずに実装できることを保証します。

「なぜ」質問に戻る。この制限は、主にベンダーのリソース制限によってもたらされます。この機能は、指定されているように莫大な労​​力を要するものではないため、ベンダーは合理的な期間内に実際に実装することができます。そのような制限がない場合、特にローカル変数を許可すると、必要な作業量が大幅に増加します。ユーザの視点(私たちのプログラマ)から、制限は全く恣意的です。

+0

いい答え。 'constexpr'は実際にコンパイラにコンパイルするのではなく**コンパイルするように指示しているので、単純化のために努力することは理解できる。しかし、静的なif(テンプレートのためだけでなく、 'constexpr'のためにも便利です。 – eudoxos

+0

私はそれがまた別の理由であると思います。あなたは無限ループを持つことはできません。無限の再帰呼び出しは単に再帰制限をforcinすることで検出できます。また、より多くのことを可能にするconstexprへの変更は、コンパイルされていない理由を迷わずにコードをコンパイルするために、ユーザーが尊重しなければならないより複雑なインバリアントを意味します。また、実際にはconstexprが動作することを「証明する」必要があり、任意のコードでそれを宣言することは理論的な観点からも困難または不可能であることは疑いがあります。 – GameDeveloper

13

理由:

constexprはC++ 11でかなり新しく、過激な概念であり、完全に新しい何かに主要な言語の標準を移行することは困難であるため。保守派のルール

(現在はC++ 14を対象としています)では、あなたの例は合法です。 trunk clangのヒントは既に-std=c++1yフラグの下に実装されています。

関連する問題