C ++で「関数を汚染する」とはどういう意味ですか?


96

CppConでのスコットシュラーの講演「紹介constexpr」の最後に「機能を害する方法はありますか」と尋ねます。次に、これは(非標準的な方法ではありますが)次の方法で実行できることを説明します。

  1. 関数throwにaを置くconstexpr
  2. 未解決の宣言 extern const char*
  3. 未解決の参照externthrow

私はここで自分の深みから少し外れているように感じますが、私は興味があります:

  • 「機能を害する」とはどういう意味ですか?
  • 彼が概説するテクニックの重要性/有用性は何ですか?

1
その用語について聞いたことがないので、簡潔な例で明確にしてください!
πάνταῥεῖ

6
@πάνταῥεῖ、はっきりさせた。これは「小さなサークルで広く知られている」という言葉
SergeyA、2015年

4
constexprは、関数へのすべての呼び出しがコンパイル時に評価されることを保証することについて話している。
TC

@TC正解- constexpr関数はコンパイル時または実行時に使用できると述べた。これは、実行時に使用できないように強制する方法ですか?いつ役に立ちますか?
sudo make install

3
特にC ++ 11ではconstexpr、制約のために関数が最も効率的な実装ではない場合が多いため、実行時に評価したくない場合があります。または、多分それはエラーケースです(彼の例のように)。
TC、

回答:


106

一般に、これは関数を使用不可にすることを意味します。たとえば、プログラムでの動的割り当ての使用を禁止したい場合は、malloc関数を「汚染」して使用できないようにすることができます。

ビデオでは、彼はより具体的な方法でそれを使用しています。これは、「コンパイル時間のみを強制する方法はありますか?」と言っている関数の汚染について話しているときに表示されるスライドを読むと明らかです。

したがって、実行時に関数を呼び出し不可能にするために関数を「汚染」することについて話しているため、定数式でのみ呼び出し可能です。テクニックは、コンパイル時のコンテキストで呼び出されたときに決して実行されない関数内に分岐を持ち、その分岐にエラーの原因となるものを含めることです。

throw式は限りそれは(あなたは、コンパイル時に例外をスローすることはできませんので、それはメモリを割り当てるように、本質的に動的な操作です)関数のコンパイル時の呼び出し中に到達されることはありませんよう、constexprの機能で許可されています。したがって、未定義のシンボルを参照するスロー式は、コンパイル時に呼び出されません(コンパイルに失敗するため)ため、実行時に使用できません。未定義のシンボルがリンカーエラーを引き起こすためです。

未定義のシンボルは、関数のコンパイル時の呼び出しでは「奇数使用」されないため、実際にはコンパイラーはシンボルへの参照を作成しないため、未定義であっても問題ありません。

役に立ちましたか?彼はそれを行う方法をデモンストレーションていますが、それが良いアイデアであるか、広く役立つとは限りません。何らかの理由でそれを行う必要がある場合は、彼のテクニックが問題を解決する可能性があります。あなたがそれを必要としないなら、あなたはそれを心配する必要はありません。

これ役立つ理由の1つは、一部の操作のコンパイル時バージョンが効率が悪い場合です。constexpr関数で許可される式の種類には制限があります(特にC ++ 11では、C ++ 14で一部の制限が削除されました)。したがって、計算を実行するための関数の2つのバージョンがある可能性があります。1つは最適ですが、constexpr関数では許可されていない式を使用し、もう1つは有効なconstexpr関数ですが、実行時に呼び出されるとパフォーマンスが低下します。時間。次善のバージョンを汚染して、ランタイム呼び出しに使用されないようにして、より効率的な(constexpr以外の)バージョンがランタイム呼び出しに使用されるようにすることができます。

注意コンパイル時に使用されるconstexpr関数のパフォーマンスは、実行時のオーバーヘッドがないため、それほど重要ではありません。コンパイラーに余分な処理を行わせることでコンパイルを遅くする可能性がありますが、実行時のパフォーマンスコストは発生しません。


1
スライドのテキストは読みましたが、彼が使用していた用語との関連はわかりませんでした。あなたがそれを説明したことは今や明らかですが、その時私はそれを見ませんでした。この素晴らしい答えをありがとう-私はこのウェブサイトが大好きです。
sudo make install

@PravasiMeet、あなた自身の質問をしてください、何か他のものについての誰かの質問のコメントをハイジャックしないでください。簡単な解決策は、すべての翻訳単位で削除済みとして定義するか、未定義のシンボルを参照する独自の定義に置き換えることです。
ジョナサンウェイクリー

17

識別子の「汚染」とは、「汚染」の後の識別子への参照がハードコンパイラエラーであることを意味します。この手法は、たとえば、非推奨にするために使用できます(関数は非推奨です。決して使用しないでください!)。

GCCには伝統的にこのためのプラグマがありました#pragma GCC poison


1
はい、しかしその話で使用されている意味ではまったくそうではありません。
TC

@TCさん、わかりました。回答する前に見て
おきましょ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.