2017-02-09 20 views
4

セットアップ上の過負荷:私はSIMD組み込み関数を使用し、いくつかのconstexprの機能内で使用したい機能を持っている/constexprの評価に分岐constexprの

を。

そのためには、私はそれをconstexprにする必要があります。しかし、SIMD組み込み関数はconstexprとマークされておらず、コンパイラの定数評価プログラムはそれらを処理できません。

私はSIMD組み込み関数を同じことをするC++ constexpr実装に置き換えようとしました。関数は実行時に3.5倍遅くなりましたが、コンパイル時に使用することができました(よろしいですか?)。

問題

どのように私は、実行時に私のプログラムを落とすことなく、定数式の内部でこの機能を使用することができますか?

いくつかのアイデア:おそらく正しい解決策が、不可能なチタンタスク:

  • すべてのコンパイラ用のコンパイラ定数式の評価者に、すべてのSIMD組み込み関数を評価する定数のサポートを、追加。より実用的な解決策は、いずれかになるであろう

  • (すなわち、constexprの、非constexprのバージョンを提供する)は、定数式内部で実行されているか否かに応じて機能をオーバーロードします。
  • 、または何らかの形で、constexprと実行時実装の間のconstexpr関数内に分岐します(つまり、関数が定数式内で実行されているかどうかを分岐内で検出します)。

どういうわけか、私は自分の問題を解決するための提案には何も触れていません。

ヒント

  • コンパイラがうまくいけば、少なくともで機能を評価しようとすると思われる場合には、関数の引数は、すべての定数式であるかどうかを検出する__builtin_constant_pを使用するラウンジで提案@RMartinhoFernandes、コンパイル時。

失敗した試みは:Jarod42 @

  • はちょうど2つの独立した機能を使用してのまっすぐ前方の提案をしました。なぜ簡単ではないのかを簡単に指摘したいと思います。このソリューションは、コールサイトで、関数がconstexprの評価を受けるかどうかが分かっていることを前提としています。しかし、そうではありません。 mineを呼び出すconstexpr関数を考えてください。私の関数のバージョンはそれを選ぶべきですか?コンパイルするためにはconstexprを選択する必要がありますが、実行時に "外側の" constexpr関数を評価することは可能です。その場合、「遅い」コンパイル時の実装を使用するため、このアプローチでは問題は解決されません。
+0

可能な重複:http://stackoverflow.com/questions/15232758/detecting-constexpr-with-sfinae and http://stackoverflow.com/questions/13299394/is-is-constexpr-possible-in-c11 –

+0

@VittorioRomeo最初のリンクは、コンパイル時に関数が評価できるかどうか、つまり、それが "マークされた" constexprであるかどうかを検出します。 2番目のリンクは、式が定数式であるかどうかを検出します。コンパイル時に現在の実行コンテキストが評価されているかどうかを分岐に使用することはできません。しかし...私は本当に試したことはありません。間違っていると証明されたいですか? – gnzlbg

+0

@VittorioRomeo @RMartinhoFernandesが(第2のリンクから) '__builtin_constant_p'を使って提案したラウンジで、関数の引数がすべて定数式であるかどうかを検出するチャットがありました。この場合、コンパイラはコンパイル時に関数を評価します。 – gnzlbg

答えて

4

doitへの呼び出しは、単にフラグを転送し、実行時またはコンパイル時にどちらか何かを実行するために呼び出すことができるconstexpr関数の内部にある場合、私はこの

constexpr int doit(int input, bool inconst = false) { 
    return inconst ? doitconsty(input) : doitfast(input); 
} 

のようにそれを行うだろう

constexpr int f(int n, bool inconst = false) { 
    /* ... */ 
    int importantInt = doit(n/42, inconst); 
    /* ... */ 
    return magicResult; 
} 

constexpr評価が間違っていないと、評価が開始されます。あなたは、ランタイムの世界にいる場合inconst

enum foo { bar = f(256, true) } 

を渡し、ちょうどあなたが追加することはできませんので、これは、オペレータのために動作しないことに留意すべきであるf

何か他のもののような
int main() { std::cout << "test-case: " << f(256); } 

を呼び出しますbooleanパラメータ。代わりに、それはあなたのために良い場合は(intboolのようなプリミティブ値のために、私たちは演算子を過負荷にすることはできませんでした)いくつかの異なる方法で値を渡すことができます。

template<typename T> 
struct maybe_const_value { 
    T t; 
    bool isconst; 
}; 

enum foo { bar = maybe_const_value{256, true} % magicTransform }; 

int main() { return maybe_const_value{265} % magicTransform; } 

オペレータ関数はinput.isconstをチェックし、実際の値としてinput.tを使用することができます。

+0

標準のC++でこれを行う方法はおそらく他にないので、私はそれを受け入れたものとしてマークしています。このソリューションは、演算子、いくつかの特別なメンバ関数などでは機能しません。 – gnzlbg