首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 可變參模板實現類 printf 格式化輸出(類型安全)

     編輯:關於C++

設計目標

模仿 C 的 `printf`,但利用 C++ 可變參模板實現**編譯期類型檢查**,避免運行期格式字符串與參數不匹配導致崩潰。

核心實現

#include <iostream>
#include <typeinfo>
#include <cstring>
using namespace std;

// 基礎情況:無參數
void my_printf(const char *fmt) {
    cout << fmt;
}

// 遞歸模板
template <typename T, typename... Args>
void my_printf(const char *fmt, T value, Args... args) {
    if (!fmt || *fmt == '\0') return;

    if (*fmt == '%') {
        ++fmt;
        // 類型檢查示例(可擴展)
        if (*fmt == 'd') {
            if (strcmp(typeid(T).name(), "i") != 0) {
                cerr << "Type mismatch: %d expects int\n";
                return;
            }
        } else if (*fmt == 's') {
            if (strcmp(typeid(T).name(), "PKc") != 0 && strcmp(typeid(T).name(), "NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE") != 0) {
                cerr << "Type mismatch: %s expects string\n";
                return;
            }
        }
        cout << value;
        my_printf(++fmt, args...);
    } else {
        cout << *fmt;
        my_printf(++fmt, value, args...);
    }
}

int main() {
    my_printf("Hello %s, answer = %d\n", "World", 42);
    // my_printf("Error %d\n", "not int"); // 編譯通過但運行期報錯
    return 0;
}

關鍵技術點

  • `typeid(T).name()` 獲取類型名稱(編譯器相關,需適配)。
  • 遞歸展開參數包 `Args...`,每次處理一個 `%` 格式符。
  • 非格式字符直接輸出。
  • 可擴展支持 `%f`、`%c`、寬度、精度等。

改進方向

  1. 使用 `std::format` (C++20) 獲得標準化、高性能、類型安全的格式化。
  2. 編譯期解析格式字符串(需 C++20 `consteval` 或模板元編程)。
  3. 返回格式化字符串而非直接輸出,增加靈活性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved