Arasındaki fark nedir __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, ve nerede belgelenir? Hangisinin kullanılacağına nasıl karar verebilirim?
Arasındaki fark nedir __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, ve nerede belgelenir? Hangisinin kullanılacağına nasıl karar verebilirim?
Yanıtlar:
__func__
, bir işlev içinde kullanıldığında işlev adını içeren bir karakter dizisi değişkenine genişleyen dolaylı olarak bildirilen bir tanımlayıcıdır. C99'da C'ye ilave edildi. Gönderen C99 / 1 §6.4.2.2:
Tanımlayıcı
__func__
, çevirmen tarafından her bir işlev tanımının açılış ayrağını hemen takip eden sanki beyanı dolaylı olarak bildirir.static const char __func__[] = "function-name";
burada işlev-adı sözcüksel olarak çevreleyen işlevin adıdır. Bu ad, işlevin süslenmemiş adıdır.
Bir makro olmadığını ve ön işleme sırasında özel bir anlamı olmadığını unutmayın.
__func__
C ++ 11'de C ++ 'a eklenmiştir, burada "bir uygulama tanımlı dize" (C ++ 11 §8.4.1 [dcl.fct.def.general] / 8) içerdiği belirtilmiştir. ( __func__
C ++ ' a eklenecek orijinal öneri N1642 idi ).
__FUNCTION__
bazı C derleyicilerinin desteklediği standart öncesi bir uzantıdır (gcc ve Visual C ++ dahil); genel olarak, __func__
desteklendiği yerde kullanmalı ve yalnızca onu desteklemeyen __FUNCTION__
bir derleyici kullanıyorsanız kullanmalısınız (örneğin, C99'u desteklemeyen ve henüz tüm C ++ 0x'i desteklemeyen Visual C ++, sağlamak __func__
).
__PRETTY_FUNCTION__
__FUNCTION__
C ++ işlevleri için işlevin imzası da dahil olmak üzere işlevin "güzel" adını içermesi dışında çoğunlukla aynı olan bir gcc uzantısıdır . Visual C ++ benzer (ama tam olarak aynı değil) bir uzantıya sahiptir __FUNCSIG__
.
Standart olmayan makrolar için derleyicinizin belgelerine başvurmak isteyeceksiniz. Visual C ++ uzantıları, C ++ derleyicisinin "Önceden Tanımlı Makrolar" MSDN belgelerinde bulunur . Gcc dokümantasyon uzantıları gcc dokümantasyon sayfası "Dizeler Olarak İşlev Adları" bölümünde açıklanmaktadır .
__FUNCTION__
, biraz farklı şeyler yaptığını unutmayın. gcc eşdeğerini verir __func__
. VC, adın dekore edilmemiş, ancak hala süslenmiş versiyonunu verir. "Foo" adlı bir yöntem için, gcc size "foo"
, VC'yi verecektir "my_namespace::my_class::foo"
.
__PRETTY_FUNCTION__
listede mevcut olarak görünüyor ve faremi üzerine getirdiğimde, işlev adı hakkında bilgi görüntülüyor, ancak derlenemiyor.
Orijinal soruyu tam olarak cevaplamamasına rağmen, muhtemelen bu googling yapan çoğu insanın görmek istediği şey budur.
GCC için:
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__
başka bir fonksiyona gömüldüğünde çalışıyor mu? Diyelim ki function1 var, argüman almıyor. function1 __func__
, hangi fonksiyon adı yazdırılacaktır, 1 veya 2'yi içeren fonksiyon2'yi çağırır ?
__func__
bir makro, şu anda hangi işlevde olursanız olun. F1'e koyar ve f2'de f1'i çağırırsanız , her zaman f1 elde edersiniz.
__PRETTY_FUNCTION__
C ++ özelliklerini işler: sınıflar, ad alanları, şablonlar ve aşırı yük
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);
}
Derleyin ve çalıştırın:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Çıktı:
f
f
static void N::C::f(int) [with T = char]
static void N::C::f(double) [with T = void]
Ayrıca, işlev adlarına sahip yığın izleri de ilginizi çekebilir: C veya C ++ ile çağrı yığını yazdırma
Ubuntu 19.04, GCC 8.3.0'da test edilmiştir.
C ++ 20 std::source_location::function_name
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf C ++ 20'ye girdi, bu yüzden bunu yapmanın başka bir yolu daha var.
Belgeler diyor ki:
constexpr const char * işlev_adı () const noexcept;
6 Döndürür: Bu nesne bir işlev gövdesindeki bir konumu temsil ediyorsa, işlev adına karşılık gelmesi gereken, uygulama tanımlı bir NTBS döndürür. Aksi takdirde, boş bir dize döndürür.
burada NTBS "Boş Sonlandırılmış Bayt Dizesi" anlamına gelir.
Destek GCC'ye geldiğinde bir deneyeceğim, GCC 9.1.0 g++-9 -std=c++2a
hala desteklemiyor.
https://en.cppreference.com/w/cpp/utility/source_location talep kullanımı şöyle olacaktır:
#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!");
}
Olası çıktı:
info:main.cpp:16:main Hello world!
bu arayanın bilgilerini nasıl döndürdüğünü ve bu nedenle günlüğe kaydetmede kullanım için mükemmel olduğunu unutmayın, ayrıca bkz: C ++ işlevinin içinde işlev adı almanın bir yolu var mı?
__func__
bölüm 8.4.1'de C ++ 0x standardında belgelenmiştir. Bu durumda, formun önceden tanımlanmış bir işlev yerel değişkeni:
static const char __func__[] = "function-name ";
burada "işlev adı" uygulama özelliğidir. Bu, bir işlev bildirdiğinizde, derleyicinin bu değişkeni işlevinize örtük olarak ekleyeceği anlamına gelir. Aynısı __FUNCTION__
ve için de geçerlidir __PRETTY_FUNCTION__
. Üst yayınlarına rağmen makro değiller. Her ne __func__
kadar C ++ 0x ekidir
g++ -std=c++98 ....
ile kod yine de derlenir __func__
.
__PRETTY_FUNCTION__
ve __FUNCTION__
burada http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names belgelenmiştir . __FUNCTION__
sadece başka bir isim __func__
. C ile __PRETTY_FUNCTION__
aynıdır __func__
ancak C ++ 'da da tip imzasını içerir.
__func__
C ++ 03'ün bir parçası değildir. C ++ 0x'de eklendi, ancak C ++ 0x henüz "C ++ standardı" değil, hala taslak formda.
VS'ye nasıl gittiğini merak edenler için.
MSVC 2015 Güncelleştirme 1, cl.exe sürümü 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>();
}
çıktı:
main () işlevinden: ana ana int __cdecl main (geçersiz) A :: f () 'den: Bir :: f <int, yüzer> f void __cdecl A <int, kayan nokta> :: f <bool> (void)
Kullanılması __PRETTY_FUNCTION__
beklendiği gibi tetikleyiciler, tanımlayıcının hatayı bildirilmeyen.