回答:
__func__
関数内で使用すると、関数名を含む文字配列変数に展開される暗黙的に宣言された識別子です。C99でCに追加されました。C99 / 1§6.4.2.2:
識別子
__func__
は、各関数定義の左中括弧の直後に、宣言がstatic const char __func__[] = "function-name";
ここでfunction-nameは、字句的に囲む関数の名前です。この名前は、関数の装飾されていない名前です。
これはマクロではなく、前処理中に特別な意味はないことに注意してください。
__func__
C ++ 11のC ++に追加されました。「実装定義の文字列」(C ++ 11§8.4.1[dcl.fct.def.general] / 8)を含むものとして指定されています。 Cの仕様として役立ちます(__func__
C ++に追加する最初の提案はN1642でした)。
__FUNCTION__
一部のCコンパイラがサポートする先行標準の拡張機能です(gccおよびVisual C ++を含む)。一般に、__func__
それがサポートされている場所で使用し、それをサポートし__FUNCTION__
ていないコンパイラーを使用している場合にのみ使用してください(例えば、Visual C ++は、C99をサポートせず、まだすべてのC ++ 0xをサポートしていません。提供する__func__
)。
__PRETTY_FUNCTION__
__FUNCTION__
C ++関数の場合、関数のシグネチャを含む関数の「かなり」の名前が含まれていることを除いて、とほぼ同じgcc拡張です。Visual C ++にも同様の(ただし完全に同一ではない)拡張子があり__FUNCSIG__
ます。
非標準のマクロについては、コンパイラのドキュメントを参照してください。Visual C ++拡張機能は、C ++コンパイラの「事前定義マクロ」のMSDNドキュメントに含まれています。gccドキュメンテーション拡張機能は、gccドキュメンテーションページの「文字列としての関数名」で説明されています。
__FUNCTION__
、動作が少し異なることに注意してください。gccはと同等のものを提供し__func__
ます。VCは、装飾されていないがまだ装飾されたバージョンの名前を提供します。「foo」という名前のメソッドの場合"foo"
、gccは、VCはを提供し"my_namespace::my_class::foo"
ます。
__PRETTY_FUNCTION__
ていて、入力するとリストに表示され、利用可能であると表示され、マウスをその上に移動すると、関数名に関する情報が表示されますが、コンパイルに失敗します。
元の質問に完全には答えていませんが、これはおそらくこれをググる人のほとんどが見たかったことです。
GCCの場合:
petanb@debian:~$ cat test.cpp
#include <iostream>
int main(int argc, char **argv)
{
std::cout << __func__ << std::endl
<< __FUNCTION__ << std::endl
<< __PRETTY_FUNCTION__ << std::endl;
}
petanb@debian:~$ g++ test.cpp
petanb@debian:~$
petanb@debian:~$ ./a.out
main
main
int main(int, char**)
__func__
、別の関数に埋め込まれている場合は機能しますか?function1があるとしましょう。引数はありません。function1はを含むfunction2を呼び出し__func__
ます。印刷される関数名は1または2ですか。
__func__
はマクロです。現在ある関数に変換されます。それをf1に入れ、f2でf1を呼び出すと、常にf1を取得します。
__PRETTY_FUNCTION__
C ++機能を処理します:クラス、名前空間、テンプレート、オーバーロード
main.cpp
#include <iostream>
namespace N {
class C {
public:
template <class T>
static void f(int i) {
(void)i;
std::cout << __func__ << std::endl
<< __FUNCTION__ << std::endl
<< __PRETTY_FUNCTION__ << std::endl;
}
template <class T>
static void f(double f) {
(void)f;
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
}
int main() {
N::C::f<char>(1);
N::C::f<void>(1.0);
}
コンパイルして実行します。
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
出力:
f
f
static void N::C::f(int) [with T = char]
static void N::C::f(double) [with T = void]
関数名の付いたスタックトレースにも興味があるかもしれません:CまたはC ++でのコールスタックの印刷
Ubuntu 19.04、GCC 8.3.0でテスト済み。
C ++ 20 std::source_location::function_name
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdfがC ++ 20に入ったので、それを行う別の方法があります。
ドキュメントは言う:
constexpr const char * function_name()const noexcept;
6戻り値:このオブジェクトが関数の本体の位置を表す場合、関数名に対応する実装定義のNTBSを返します。それ以外の場合は、空の文字列を返します。
ここで、NTBSは「Null Terminated Byte String」を意味します。
サポートがGCCに届いたら、GCC 9.1.0 g++-9 -std=c++2a
がまだサポートされていないときに試してみます。
https://en.cppreference.com/w/cpp/utility/source_locationの使用法は次のようになります。
#include <iostream>
#include <string_view>
#include <source_location>
void log(std::string_view message,
const std::source_location& location std::source_location::current()
) {
std::cout << "info:"
<< location.file_name() << ":"
<< location.line() << ":"
<< location.function_name() << " "
<< message << '\n';
}
int main() {
log("Hello world!");
}
可能な出力:
info:main.cpp:16:main Hello world!
これが呼び出し元の情報を返す方法に注意してください。したがって、ロギングでの使用に最適です。C++関数内の関数名を取得する方法はありますか。
__func__
セクション8.4.1のC ++ 0x標準に文書化されています。この場合は、次の形式の事前定義された関数ローカル変数です。
static const char __func__[] = "function-name ";
ここで、「関数名」は実装固有です。つまり、関数を宣言すると、コンパイラーはこの変数を暗黙的に関数に追加します。同じことが真のである__FUNCTION__
と__PRETTY_FUNCTION__
。それらが大文字であるにもかかわらず、それらはマクロではありません。が__func__
C ++ 0xのに加えています
g++ -std=c++98 ....
は引き続きを使用してコードをコンパイルします__func__
。
__PRETTY_FUNCTION__
そして__FUNCTION__
ここに記述されていhttp://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names。__FUNCTION__
はの別名です__func__
。C __PRETTY_FUNCTION__
と同じです__func__
が、C ++では型シグネチャも含まれています。
__func__
C ++ 03の一部ではありません。C ++ 0xで追加されましたが、C ++ 0xはまだ「C ++標準」ではなく、まだドラフト形式です。
それがVSでどうなるのか疑問に思う人のために。
MSVC 2015 Update 1、cl.exeバージョン19.00.24215.1:
#include <iostream>
template<typename X, typename Y>
struct A
{
template<typename Z>
static void f()
{
std::cout << "from A::f():" << std::endl
<< __FUNCTION__ << std::endl
<< __func__ << std::endl
<< __FUNCSIG__ << std::endl;
}
};
void main()
{
std::cout << "from main():" << std::endl
<< __FUNCTION__ << std::endl
<< __func__ << std::endl
<< __FUNCSIG__ << std::endl << std::endl;
A<int, float>::f<bool>();
}
出力:
main()から: メイン メイン int __cdecl main(void) A :: f()から: A <int、float> :: f f void __cdecl A <int、float> :: f <bool>(void)
__PRETTY_FUNCTION__
トリガーを使用すると、予想どおり、未宣言の識別子エラーが発生します。