std::time など、std 関数の動作をオーバーライドしたいと思います。std::time を呼び出して、カスタム関数を介してルーティングすることは可能ですか?
5 に答える
一般的に言えば、std
名前空間は立ち入り禁止です。名前空間に新しい関数、オーバーロード、クラスなどを追加することstd
は、**未定義の動作*です。
唯一の例外は、テンプレートの特殊化です。std
名前空間で関数の特殊化を提供できます。これがよく行われる関数はstd::swap
.
これは非常に悪い考えのように聞こえます。true
orを再定義するようなものfalse
です。より良い方法は、独自のラッパー関数を作成することです。たとえば、内部tim_time()
で呼び出す場合としない場合があります。std::time()
それを呼び出す代わりにstd::time
、別の名前空間を介してオーバーライドする可能性のあるすべての呼び出しをルーティングします。
namespace mystd{
using namespace std;
void time() { ... }
}
// ...
mystd::time(); // not std::time
mystd::copy(...); // calls std::copy, unless you override it like time()
次に、への呼び出しmystd::time
は、関数の変更されたバージョンを呼び出します。たとえば、オーバーライドされていない関数を呼び出すmystd::copy
と、元の std 関数に正しく解決されます。
一部のプラットフォームでは、これを実行できます。ソースコードで、関数を定義します。
extern "C" time_t time(time_t *value)
{
...
}
運が良ければ、リンカーはstd::time
標準ライブラリのバージョンよりも緊密にバージョンをバインドします。もちろん、これが機能する、または希望どおりにリンクされるという保証はありません。また、欠点として、元のにアクセスできなくなりますstd::time
。
他の誰もが投稿しているように、これは移植可能な動作ではありません。Linuxで動作すると確信しています。また、Windowsでは機能しないこともかなり確信しています(リンカーが競合について不平を言っています)。
ポータブルではありません。標準が何が起こるかを定義していないことを理解すると、通常、名前空間 std で好きなシンボルや関数を定義したり、それらのシンボルを定義するライブラリにリンクしたりできます。それは単に未定義の動作です。したがって、あなたができることは、それを吸って見て、コンパイラの次のリリースで壊れないことを願うことだけです.
つまり、ほとんどのコンパイラでは、「実際の」std::time との 1 つの定義ルールの衝突を回避すれば、おそらくほとんど機能します。これは、ほとんどのコンパイラが実際には名前空間 std で特別なことを何も行わず、それを実装するために使用するヘッダー ファイルとライブラリが、自分で作成できるヘッダー ファイルとライブラリと実際には何の違いもないためです。
ただし、このように標準から外れることは、ほとんどの場合、非常に悪い考えであるというディマの意見はまったく正しい. 基本的に std::time にロギングを追加したいができないというデバッグ地獄に行き詰まっている場合は、考える価値があります。そうでなければそこに行かないでください。いくつかのコードをテストして、さまざまな時点で正しく機能するかどうかを確認する場合は、そのコードに、呼び出す必要がある時間関数を指定するパラメーター (またはテンプレート パラメーター) を渡します。