◐ Shell
clean mode source ↗

テキストマクロの置換 - cppreference.com

プリプロセッサはテキストマクロの置換をサポートします。 関数ライクなテキストマクロの置換もサポートされます。

構文

#define identifier replacement-list(オプション) (1)
#define identifier( parameters ) replacement-list(オプション) (2)
#define identifier( parameters, ... ) replacement-list(オプション) (3) (C++11以上)
#define identifier( ... ) replacement-list(オプション) (4) (C++11以上)
#undef identifier (5)

説明

#define 指令

#define 指令は identifier をマクロとして定義します。 これは、すべての一連の identifier の出現を replacement-list に置き換えるようコンパイラに指示します。 オプションでさらに処理されることあリます。 識別子がすでに何らかの種類のマクロとして定義されている場合、その定義が同一でなければ、プログラムは ill-formed です。

オブジェクトライクなマクロ

オブジェクトライクなマクロは定義された identifier のすべての出現を replacement-list で置き換えます。 #define 指令のバージョン (1) はまさにそのように動作します。

関数ライクなマクロ

関数ライクなマクロは、定義された identifier のそれぞれの出現を replacement-list で置き換え、さらに任意の数の引数を取り、 replacement-list 内の対応するあらゆる parameters の出現を置き換えます。

関数ライクなマクロの呼び出しの構文は関数呼び出しの構文に似ています。 次のプリプロセッサトークンとして ( が続くマクロ名のそれぞれの実体は、 replacement-list によって置き換えられるトークンの並びを導入します。 この並びは対応する ) トークンによって終了します (間に入る開き括弧と閉じ括弧の対応する組はスキップされます)。

バージョン (2) の場合、実引数の数はマクロ定義内の仮引数の数と同じでなければなりません。 バージョン (3,4) の場合、実引数の数は仮引数の数 (... は数えません) と同じまたは (C++20以上)より多くなければなりません。 そうでなければ、プログラムは ill-formed です。 識別子が関数表記でない場合、すなわち、後に括弧が続かない場合は、一切置換されません。

#define 指令のバージョン (2) は単純な関数ライクなマクロを定義します。

#define 指令のバージョン (3) は可変長引数を持つ関数ライクなマクロを定義します。 追加の引数 (可変長引数と呼ばれます) は、置換される識別子として供給される __VA_ARGS__ を用いてアクセスすることができます。 __VA_ARGS__ は実引数で置換されます。

#define 指令のバージョン (4) は可変長引数を持つけれども正規の引数を持たない関数ライクなマクロを定義します。 引数 (可変長引数と呼ばれます) は、置換される識別子として供給される __VA_ARGS__ でのみアクセスできます。 __VA_ARGS__ は実引数で置換されます。

バージョン (3,4) の場合、 replacement-list はトークンの並び __VA_OPT__ ( content ) を含むことができます。 これは、 __VA_ARGS__ が空でない場合は content に置換され、そうでなければ、空に展開されます。

#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)
#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)
#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })
F(a, b, c) // f(0, a, b, c) で置換されます。
F()        // f(0) で置換されます。
G(a, b, c) // f(0, a, b, c) で置換されます。
G(a, )     // f(0, a) で置換されます。
G(a)       // f(0, a) で置換されます。
SDEF(foo);       // S foo; で置換されます。
SDEF(bar, 1, 2); // S bar = { 1, 2 }; で置換されます。
(C++20以上)

ノート: 関数ライクなマクロの実引数に、対応する開き括弧と閉じ括弧の組で保護されていないコンマが含まれている場合 (一番よくあるケースは assert(std::is_same_v<int, int>);BOOST_FOREACH(std::pair<int,int> p, m) のようなテンプレートの実引数リストです)、コンマはマクロの実引数の区切りとして解釈されます。 これは実引数の数の不一致によるコンパイルの失敗を発生させます。

予約済みのマクロ名

何らかの標準ライブラリヘッダをインクルードする翻訳単位は、いかなる標準ライブラリヘッダで宣言されている名前も #define または #undef してはなりません。

標準ライブラリの任意の一部を使用する翻訳単位は、以下と字句的に同一な名前を #define または #undef してはなりません。

ただし、 likely および unlikely は関数ライクなマクロとして定義しても構いません。

(C++20以上)

そうでなければ、動作は未定義です。

# および ## 演算子

関数ライクなマクロにおいて、 replacement-list 内の識別子の前の # 演算子は、引数の置換によって識別子を処理し、その結果を引用符で囲み、実質的に文字列リテラルを作成します。 さらに、プリプロセッサは必要に応じて、埋め込まれる文字列リテラル (もしあれば) の周りの引用符をエスケープするためにバックスラッシュを追加し、文字列内のバックスラッシュを二重化します。 すべての先行および後続するホワイトスペースは除去され、テキストの途中 (埋め込まれた文字列リテラル内部は除く) のホワイトスペースのあらゆる並びは単一のスペースに圧縮されます。 この操作は「文字列化」と呼ばれます。 文字列化の結果が有効な文字列リテラルでない場合、動作は未定義です。

# が __VA_ARGS__ の前に現れた場合、展開された __VA_ARGS__ 全体が引用符で囲まれます。

#define showlist(...) puts(#__VA_ARGS__)
showlist();            // puts("") に展開されます。
showlist(1, "x", int); // puts("1, \"x\", int") に展開されます。
(C++11以上)

replacement-list 内の任意の2つの連続する識別子の間の ## 演算子は、その2つの識別子 (マクロ展開されない) の引数置換を処理し、その後、その結果を連結します。 この操作は「連結」または「トークンの貼り合わせ」と呼ばれます。 合わせて有効なトークンを形成するトークンのみが連結できます。 より長い識別子を形成する識別子、数値を形成する数字、または += を形成する += 演算子などです。 コメントはマクロ置換が考慮される前にテキストから除去されるため、 /* を連結してコメントを作ることはできません。 連結の結果が有効なトークンでない場合、動作は未定義です。

ノート: コンパイラによってはコンマの後 __VA_ARGS__ の前に ## が現れることを許容する拡張を提供します。 この場合 ## は可変長引数が存在するとき何もしませんが、可変長引数が存在しないときはコンマを除去します。 これにより fprintf (stderr, format, ##__VA_ARGS__) などのマクロを定義することを可能とします。

#undef 指令

#undef 指令は identifier の定義を解除します。 つまり、 #define 指令による identifier の以前の定義を取り消します。 その識別子に紐付くマクロがない場合、この指令は無視されます。

定義済みのマクロ

以下のマクロ名はすべての翻訳単位であらかじめ定義されています。

__cplusplus

使用している C++ 標準のバージョンを表します。 199711L(C++11未満)、201103L(C++11)、201402L(C++14) または 201703L(C++17) に展開されます。
(マクロ定数)

__STDC_HOSTED__

処理系がホスト環境 (OS の下で実行される) の場合は整数定数 1、フリースタンディング環境 (OS なしで実行される) の場合は 0 に展開されます。
(マクロ定数)

__FILE__

文字列リテラルとしての現在のファイルの名前に展開されます。 #line 指令によって変更できます。
(マクロ定数)

__LINE__

整数定数としてのソースファイルの行番号に展開されます。 #line 指令によって変更できます。
(マクロ定数)

__DATE__

翻訳の日付、 "Mmm dd yyyy" 形式の文字列リテラルに展開されます。 日が10より小さい場合、「dd」の最初の文字は空白になります。 月の名前は std::asctime() によって生成されたかのようになります。
(マクロ定数)

__TIME__

翻訳の時刻、 "hh:mm:ss" 形式の文字列リテラルに展開されます。
(マクロ定数)

__STDCPP_DEFAULT_NEW_ALIGNMENT__

(C++17)

アライメント非対応の operator new への呼び出しによって生成されるアライメントの値を持つ std::size_t のリテラルに展開されます (それより大きなアライメントは operator new(std::size_t, std::align_val_t) などのアライメント対応のオーバーロードに渡されます)。
(マクロ定数)

処理系によっては以下の追加のマクロ名があらかじめ定義されていることがあります。

__STDC__

処理系定義の値 (存在する場合)。 一般的には C に準拠していることを表すために使用されます。
(マクロ定数)

__STDC_VERSION__

(C++11)

処理系定義の値 (存在する場合)。
(マクロ定数)

__STDC_ISO_10646__

(C++11)

wchar_t が Unicode を使用する場合は、 yyyymmL 形式の整数定数に展開されます。 この日付はサポートされている Unicode の最新のバージョンを表します。
(マクロ定数)

__STDC_MB_MIGHT_NEQ_WC__

(C++11)

基本文字のメンバに対して 'x' == L'x' が false かもしれない場合 (wchar_t に Unicode を使用する EBCDIC ベースのシステムなど)、 1 に展開されます。
(マクロ定数)

__STDCPP_STRICT_POINTER_SAFETY__

処理系が厳密な std::pointer_safety を持つ場合は、 1 に展開されます。
(マクロ定数)

__STDCPP_THREADS__

(C++11)

プログラムが複数の実行のスレッドを持つことができる場合は 1 に展開されます。
(マクロ定数)

(__FILE__ および __LINE__ を除いて) これらのマクロの値は翻訳単位を通して一定に保たれます。 これらのマクロの再定義および定義解除の試みの結果は未定義動作です。

ノート: すべての関数の本体のスコープ内において、その関数の名前を処理系定義の書式で保持する静的な文字配列として定義される、 __func__(C++11以上) という名前の特別な関数ローカルな定義済みの変数が存在します。 これは定義済みのマクロではありませんが、例えば assert によって、 __FILE____LINE__ と一緒に使用されます。

言語機能テストマクロ

以下のマクロはすべての翻訳単位であらかじめ定義されています。

__cpp_aggregate_bases

整数リテラル 201603L に展開されます。
(マクロ定数)

__cpp_aggregate_nsdmi

整数リテラル 201304L に展開されます。
(マクロ定数)

__cpp_aggregate_paren_init

整数リテラル 201902L に展開されます。
(マクロ定数)

__cpp_alias_templates

整数リテラル 200704L に展開されます。
(マクロ定数)

__cpp_aligned_new

整数リテラル 201606L に展開されます。
(マクロ定数)

__cpp_attributes

整数リテラル 200809L に展開されます。
(マクロ定数)

__cpp_binary_literals

整数リテラル 201304L に展開されます。
(マクロ定数)

__cpp_capture_star_this

整数リテラル 201603L に展開されます。
(マクロ定数)

__cpp_char8_t

整数リテラル 201811L に展開されます。
(マクロ定数)

__cpp_conditional_explicit

整数リテラル 201806L に展開されます。
(マクロ定数)

__cpp_constexpr

整数リテラル 201907L に展開されます。
(マクロ定数)

__cpp_constexpr_dynamic_alloc

整数リテラル 201907L に展開されます。
(マクロ定数)

__cpp_constinit

整数リテラル 201907L に展開されます。
(マクロ定数)

__cpp_coroutines

整数リテラル 201902L に展開されます。
(マクロ定数)

__cpp_decltype

整数リテラル 200707L に展開されます。
(マクロ定数)

__cpp_decltype_auto

整数リテラル 201304L に展開されます。
(マクロ定数)

__cpp_deduction_guides

整数リテラル 201907L に展開されます。
(マクロ定数)

__cpp_delegating_constructors

整数リテラル 200604L に展開されます。
(マクロ定数)

__cpp_enumerator_attributes

整数リテラル 201411L に展開されます。
(マクロ定数)

__cpp_fold_expressions

整数リテラル 201603L に展開されます。
(マクロ定数)

__cpp_generic_lambdas

整数リテラル 201304L に展開されます。
(マクロ定数)

__cpp_guaranteed_copy_elision

整数リテラル 201606L に展開されます。
(マクロ定数)

__cpp_hex_float

整数リテラル 201603L に展開されます。
(マクロ定数)

__cpp_if_constexpr

整数リテラル 201606L に展開されます。
(マクロ定数)

__cpp_impl_destroying_delete

整数リテラル 201806L に展開されます。
(マクロ定数)

__cpp_impl_three_way_comparison

整数リテラル 201907L に展開されます。
(マクロ定数)

__cpp_inheriting_constructors

整数リテラル 201511L に展開されます。
(マクロ定数)

__cpp_init_captures

整数リテラル 201304L に展開されます。
(マクロ定数)

__cpp_initializer_lists

整数リテラル 200806L に展開されます。
(マクロ定数)

__cpp_inline_variables

整数リテラル 201606L に展開されます。
(マクロ定数)

__cpp_lambdas

整数リテラル 200907L に展開されます。
(マクロ定数)

__cpp_modules

整数リテラル 201907L に展開されます。
(マクロ定数)

__cpp_namespace_attributes

整数リテラル 201411L に展開されます。
(マクロ定数)

__cpp_noexcept_function_type

整数リテラル 201510L に展開されます。
(マクロ定数)

__cpp_nontype_template_args

整数リテラル 201411L に展開されます。
(マクロ定数)

__cpp_nontype_template_parameter_auto

整数リテラル 201606L に展開されます。
(マクロ定数)

__cpp_nontype_template_parameter_class

整数リテラル 201806L に展開されます。
(マクロ定数)

__cpp_nsdmi

整数リテラル 200809L に展開されます。
(マクロ定数)

__cpp_range_based_for

整数リテラル 201603L に展開されます。
(マクロ定数)

__cpp_raw_strings

整数リテラル 200710L に展開されます。
(マクロ定数)

__cpp_ref_qualifiers

整数リテラル 200710L に展開されます。
(マクロ定数)

__cpp_return_type_deduction

整数リテラル 201304L に展開されます。
(マクロ定数)

__cpp_rvalue_references

整数リテラル 200610L に展開されます。
(マクロ定数)

__cpp_sized_deallocation

整数リテラル 201309L に展開されます。
(マクロ定数)

__cpp_static_assert

整数リテラル 201411L に展開されます。
(マクロ定数)

__cpp_structured_bindings

整数リテラル 201606L に展開されます。
(マクロ定数)

__cpp_template_template_args

整数リテラル 201611L に展開されます。
(マクロ定数)

__cpp_threadsafe_static_init

整数リテラル 200806L に展開されます。
(マクロ定数)

__cpp_unicode_characters

整数リテラル 200704L に展開されます。
(マクロ定数)

__cpp_unicode_literals

整数リテラル 200710L に展開されます。
(マクロ定数)

__cpp_user_defined_literals

整数リテラル 200809L に展開されます。
(マクロ定数)

__cpp_using_enum

整数リテラル 201907L に展開されます。
(マクロ定数)

__cpp_variable_templates

整数リテラル 201304L に展開されます。
(マクロ定数)

__cpp_variadic_templates

整数リテラル 200704L に展開されます。
(マクロ定数)

__cpp_variadic_using

整数リテラル 201611L に展開されます。
(マクロ定数)
(C++20以上)

#include <iostream>

// 関数ファクトリを作成して、それを使用します。
#define FUNCTION(name, a) int fun_##name() { return a;}

FUNCTION(abcd, 12)
FUNCTION(fff, 2)
FUNCTION(qqq, 23)

#undef FUNCTION
#define FUNCTION 34
#define OUTPUT(a) std::cout << "output: " #a << '\n'

// マクロ定義内でマクロを使用する例。
#define WORD "Hello "
#define OUTER(...) WORD #__VA_ARGS__

int main()
{
    std::cout << "abcd: " << fun_abcd() << '\n';
    std::cout << "fff: " << fun_fff() << '\n';
    std::cout << "qqq: " << fun_qqq() << '\n';
    std::cout << FUNCTION << '\n';
    OUTPUT(million);               //ダブルクォートがないことに注意。

    std::cout << OUTER(World) << '\n';
    std::cout << OUTER(WORD World) << '\n';
}

出力:

abcd: 12
fff: 2
qqq: 23
34
output: million
Hello World
Hello WORD World

関連項目