LoginSignup
27
25

More than 5 years have passed since last update.

可変長引数をもつ関数(printf, ioctl, etc..)をラップする方法まとめ

Posted at

可変長引数を持つ関数をラップする方法を調べました。
C++11以降であれば variadic templates を使うのが良いと思われます。

test.cpp
#include <stdio.h>
#include <stdarg.h>

// [C++11 ~] variadic templates
template <typename ... Args>
void Printf(const char *format, Args const & ... args) {
    // int printf(const char *format, ...);
    printf(format, args ...);
}

// [C/C++] stdarg
void vPrintf(const char *format, ...) {
    va_list va;
    va_start(va, format);
    // int vprintf(const char *format, va_list ap);
    vprintf(format, va);
    va_end(va);
}

// [C/C++] macro __VA_ARGS__
#define PRINTF(format, ...) printf(format, __VA_ARGS__)

// [C/C++][GCC only] macro ##__VA_ARGS__
#define PRINTF_GCC(format, ...) printf(format, ##__VA_ARGS__)

int main(int argc, char const* argv[])
{
    // [C++11 ~] variadic templates
    Printf("%s : %d\n", "Printf", 20);

    // [C/C++] stdarg
    // va_listをサポートしている必要がある
    vPrintf("%s : %d\n", "vPrintf", 20);

    // [C/C++] macro __VA_ARGS__
    PRINTF("%s : %d\n", "PRINTF", 20);

    // __VA_ARGS__は最低1個引数が必要な仕様なため、カンマが入ってしまい以下はエラーになる
    // PRINTF("PRINTF format only\n");

    // [C/C++][GCC only] macro ##__VA_ARGS__
    // GCC拡張であれば未指定の場合最後のカンマを除去してくれる
    PRINTF_GCC("%s : %d\n", "PRINTF_GCC", 20);
    PRINTF_GCC("PRINTF_GCC : format only\n");

    return 0;
}
実行結果
$ g++ -std=c++11 test.cpp && ./a.out
Printf : 20
vPrintf : 20
PRINTF : 20
PRINTF_GCC : 20
PRINTF_GCC : format only

参考

本の虫: Variadic Templatesの解説
c++ - 可変長引数関数のラッピング方法 - スタック・オーバーフロー
[C言語] 可変引数マクロの作り方 - Qiita
C/C++での可変引数(stdarg他)

27
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
25