2015-09-04 12 views
26

ソースコードの唯一の違いが1つのconstexprの有無である2つのプログラムがある場合、プログラムの意味が変更される可能性はありますか?'constexpr'を追加して動作を変更できますか?

言い換えれば、可能であればconstexprを推測することを実際に難しくしようとコンパイラに指示するコンパイラオプションがある場合、既存の標準コードを破るか、またはその意味を悪く変更するでしょうか?

元の開発者が可能であればconstexprをC++ 11の前に書かれたコードに含めるのを忘れたというコードベースを扱うことを想像してみてください。コンパイラがあなたの作業に取り組むのを助けるためにconstexprを推測するのは素晴らしいことです。もちろん、おそらく、この推論を行うたびに警告し、後でconstexprを明示的に追加するよう促すべきでしょう。しかしそれはまだ有用である。私の心配は、物事を壊すかもしれないということですか?

これまでのところ、constexprの機能は暗黙的にinlineであり、inlineを追加すると状況が変わることがあります。たとえば、1つの定義ルールを破った場合などです。

+0

たとえば、標準でマークされていない関数をconstexprとしてマークしてSFINAEを介して異なる動作を引き起こす可能性がある場合(これは最終的には許可されていませんでした)、[ -constexpr標準ライブラリ関数はconstexpr?](http://stackoverflow.com/q/27744079/1708801) –

+0

ありがとう@ShafikYaghmour。相違を見つけるためにSFINAEでいくつかの実験を行ったが、できなかった。私は私の例があまりにも単純すぎると思う:) –

+2

私は、[SFINAE breaks where example](http://stackoverflow.com/a/21319414/1708801)の定数式で未定義の振る舞いが異なるためです。これが合致しているかどうかにかかわらず、私はまだ回答がありません。まったく同じではありませんが、異なる実装がSFINAEをどのように壊すかを確認できます。 –

答えて

12

簡単なトリックがあります:

template<int n>struct i{}; 
int foo(int){return 0;} 
constexpr int foo(char){return 'a';} 

template<class T=int, T x=1,i<foo(x)>* =nullptr> 
bool bar(){return true;} 
template<class T=int, T x=1,class...Ts> 
bool bar(Ts...){return false;} 

int foo(int)がconstexprのであれば、barの異なる過負荷がデフォルトで選択されています。

異なるコードを実行すると、動作が変更される可能性があります。

live example(単に#define Xがコメントアウトされています)。


例の設計:

char過負荷が悪い形成されることから、上記のコードを防ぎ、すべてのテンプレートが有効な専門を持っている必要がありますように、何の診断は、必要ありません。 foo<char>がそれを供給します。実際には、その存在は必要ではありません.ADLは遠くからにオーバーロードされたfooを見つけ、次にsome_type*Tとして渡します。これは、コードが不正であることをコンパイル単位で証明できないことを意味します。

Ts...は、barの優先度が低くなります。したがって、最初のものが一致すれば、あいまいさはありません。 (foo(x)でないSFINAEがconstexprではないために)最初の1つが一致しない場合にのみ、2番目のオーバーロードが呼び出されます(または、例えば、誰かが引数を渡した場合)。

+0

Perfect。私はclangとg ++の両方で 'constexpr'に依存する行動を示すものを作るために苦労していました。しかし、これは3.5.0とg ++ 5.2.0の両方でトリックを行います。 –

+0

..私はこれが、コンパイル時に特定の関数が 'constexpr'かどうかを検出することが可能であることを示していると思います。これはクールなようですが、 'constexpr'を推測することは、これらのテストの結果を変えるので危険であることを意味します。最後に、私はそれを理解するようになりました。私はこれがエラーを与えるべきだと思う - 最良のオーバーロードが 'constexpr'でない場合、定数式を必要とするコンテキストで呼び出されるとエラーが発生するはずです。 (私の謙虚な意見では、ちょうど最後の数分で形成されました) –

+2

@AaronMcDaidエラーは直後のコンテキストにあるため、エラーではなく置換エラーが発生します。 SFINAEは、ほとんどの "シグネチャ"の変更(存在していても)がC++で異なるコンパイル時と実行時の動作を引き起こす可能性があることを意味し、完全に準拠することは不可能です。しかし、これが起こるケースは、(上記の場合を含めて私はそれを見たすべてのケースで)病理学的なものです。 – Yakk

4

は、ソースコード内の唯一の違いは1 constexprのの 存在または非存在である二つのプログラムを考えると、それが可能なプログラム変更の意味は ということでしょうか?

はい、これは少なくともconstexpr関数に当てはまります。実装がどの標準関数にconstexprとマークされているかを選択できない理由は、主な問題はユーザーがSFINAEを介して異なる動作を観察する可能性があることです。これは言っているLWG issue 2013: Do library implementers have the freedom to add constexpr?に記載されています(強調鉱山):

いくつかの懸念は、この問題は発散のための結果の十分な 考えずに解決されたことをWPの状態に投票 のための完全な委員会に提示したときに表明 ユーザはSFINAEを使用して、別の同一のコードと異なる動作を観察することができます。問題はレビューステータスに戻され、大きなグループのポートランドで再び説明される になります。ポートランドに関する注記: John Spicerは、LWG内のこのような の議論でコアの懸念を表明することに合意しました。

+1

@AaronMcDaid実際にライブサンプルを作成しようとしていますが、そのコードを見てからしばらくして、詳細が正しいことを確認したいと思います。 –

+0

特定の 'constexpr'関数には本当です。それとは別に、 'constexpr'も他の用途もありますので、部分的にはそうです。 – edmz

+0

(私はこの答えに書いた以前のコメントを削除しました。なぜなら、 'constexpr'の存在により動作が変化する例を作成するのにまだ使用できないからです) –

関連する問題