Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

__PRETTY_FUNCTION__, __FUNCTION__, __func__ ใน C/C++: ความแตกต่างและการใช้งาน

Identifier ทั้งสามใช้สำหรับดึงข้อมูลฟังก์ชันปัจจุบัน แตกต่างกันในระดับรายละเอียดและ Standard Compliance

ตารางเปรียบเทียบ

IdentifierStandardเนื้อหาตัวอย่าง Output
__func__C99, C++11Function Name เท่านั้น"main", "foo"
__FUNCTION__GNU Extension (C/C++)เหมือน __func__"main"
__PRETTY_FUNCTION__GNU Extension (GCC/Clang)Pretty Signature (Class, Template, Const, Ref, Params)"void MyClass::method() const"
__FUNCSIG__MSVC ExtensionPretty Signature (MSVC Format)"void __cdecl MyClass::method(void) const"

ตัวอย่างเปรียบเทียบ

#include <iostream>

class MyClass {
public:
    void method() const {
        std::cout << "__PRETTY_FUNCTION__: " << __PRETTY_FUNCTION__ << '\n';
        std::cout << "__func__: " << __func__ << '\n';
    }
};

template <typename T>
void templateFunc(T) {
    std::cout << "__PRETTY_FUNCTION__: " << __PRETTY_FUNCTION__ << '\n';
}

int main() {
    std::cout << "__FUNCTION__: " << __FUNCTION__ << '\n';
    MyClass().method();
    templateFunc(42);
}

ผลลัพธ์ (GCC/Clang)


__FUNCTION__: main
__PRETTY_FUNCTION__: void MyClass::method() const
__func__: method
__PRETTY_FUNCTION__: void templateFunc(T) [with T = int]

การประยุกต์: Portable Logging Macro


// Cross-Compiler Function Name Macro
#if defined(__GNUC__) || defined(__clang__)
    #define FUNC_NAME __PRETTY_FUNCTION__
#elif defined(_MSC_VER)
    #define FUNC_NAME __FUNCSIG__
#else
    #define FUNC_NAME __func__
#endif

#define LOG(msg) std::cerr << "[" << FUNC_NAME << "] " << msg << '\n'

void process() {
    LOG("Start processing");
    // ...
    LOG("End processing");
}

ใน Lambda Expressions


auto lambda = []() {
    std::cout << __func__ << '\n'; // GCC: "", MSVC: "operator()"
};

ข้อจำกัด

  • ไม่ใช่ Preprocessor Macro -> ไม่ทำงานใน #if
  • __func__ เป็น `static const char[]` Local Variable
  • C++ Standard ไม่รวม __PRETTY_FUNCTION__ (Vendor Extension)

สรุป

  • Portable Code: ใช้ __func__ (C++11 Standard)
  • Debug/Log Detailed Signature: ใช้ __PRETTY_FUNCTION__ (GCC/Clang) หรือ __FUNCSIG__ (MSVC)
  • สร้าง Portable Macro ด้วย #ifdef ตรวจสอบ Compiler