以下のコードでは、簡単な関数を定義していますlog
。main
ないそれを呼び出すには、 を呼び出しますstd::log
。それにもかかわらず、自分の がlog
呼び出され、画面に「log!」と表示されます。理由を知っている人はいますか? 私は G++ 4.7 と clang++ 3.2 を使用しています。
#include <iostream>
#include <cmath>
double log(const double x) { std::cout << "log!\n"; return x; }
int main(int argc, char *argv[])
{
std::log(3.14);
return 0;
}
ベストアンサー1
C++ 標準 17.6.1.2 パラグラフ 4 (強調は筆者による):
条項 18 から 30 および付録 D で注記されている場合を除き、各ヘッダーの内容は、C 標準ライブラリ (1.2) または C Unicode TR で指定されている
cname
対応するヘッダーの内容と同じでname.h
、組み込まれているものとみなされます。ただし、C++ 標準ライブラリでは、宣言 (C でマクロとして定義されている名前を除く) は、名前空間の名前空間スコープ (3.3.6) 内にありますstd
。これらの名前が最初にグローバル名前空間スコープ内で宣言され、その後std
明示的に名前空間に挿入されるかどうかは指定されていません。使用宣言(7.3.3)。
double log(double)
g++ は後者の方法を採用しており、同じヘッダー ファイルの一部を C と C++ で再利用できます。そのため、g++ はグローバル名前空間で宣言および定義できます。
セクション17.6.4.3.3第3項および第4項:
外部リンケージで宣言された標準 C ライブラリの各名前は、
extern "C"
名前空間std
とグローバル名前空間の両方でリンケージ付きの名前として使用するために実装用に予約されています。
extern "C"
外部リンケージで宣言された標準 C ライブラリの各関数シグネチャは、とリンケージの両方を持つ関数シグネチャとして使用するために、またはグローバル名前空間内の名前空間スコープの名前として使用するために実装用に予約されextern "C++"
ています。
そして、セクション 17.6.4.3 の段落 2 の先頭には、次の記述があります。
プログラムが、この条項で明示的に許可されている場合を除き、名前が予約されているコンテキストで名前を宣言または定義した場合、その動作は未定義です。
一方、あなたはない::log
いかなる形であれ宣言または定義する。
ただし、g++ ツールチェーンがエラー メッセージを表示しないのは残念です。