名前空間
変種
操作

テキストマクロの置換

提供: cppreference.com
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (非推奨)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
 

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

目次

[編集] 構文

#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) // replaced by f(0, a, b, c)
F()        // replaced by f(0)
G(a, b, c) // replaced by f(0, a, b, c)
G(a, )     // replaced by f(0, a)
G(a)       // replaced by f(0, a)
SDEF(foo);       // replaced by S foo;
SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 };
(C++20およびそれ以降)

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

[編集] # および ## 演算子

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

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

#define showlist(...) puts(#__VA_ARGS__)
showlist();            // expands to puts("")
showlist(1, "x", int); // expands to 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_alias_templates
整数リテラル 200704L に展開されます。
(マクロ定数)
__cpp_aligned_new
整数リテラル 201606L に展開されます。
(マクロ定数)
__cpp_attributes
整数リテラル 200809L に展開されます。
(マクロ定数)
__cpp_binary_literals
整数リテラル 201304L に展開されます。
(マクロ定数)
__cpp_capture_star_this
整数リテラル 201603L に展開されます。
(マクロ定数)
__cpp_constexpr
整数リテラル 201603L に展開されます。
(マクロ定数)
__cpp_decltype
整数リテラル 200707L に展開されます。
(マクロ定数)
__cpp_decltype_auto
整数リテラル 201304L に展開されます。
(マクロ定数)
__cpp_deduction_guides
整数リテラル 201703L に展開されます。
(マクロ定数)
__cpp_delegating_constructors
整数リテラル 200604L に展開されます。
(マクロ定数)
__cpp_enumerator_attributes
整数リテラル 201411L に展開されます。
(マクロ定数)
__cpp_explicit_bool
整数リテラル 201806L に展開されます。
(マクロ定数)
__cpp_fold_expressions
整数リテラル 201603L に展開されます。
(マクロ定数)
__cpp_generic_lambdas
整数リテラル 201304L に展開されます。
(マクロ定数)
__cpp_guaranteed_copy_elision
整数リテラル 201606L に展開されます。
(マクロ定数)
__cpp_hex_float
整数リテラル 201603L に展開されます。
(マクロ定数)
__cpp_if_constexpr
整数リテラル 201606L に展開されます。
(マクロ定数)
__cpp_inheriting_constructors
整数リテラル 201511L に展開されます。
(マクロ定数)
__cpp_init_captures
整数リテラル 201304L に展開されます。
(マクロ定数)
__cpp_initializer_lists
整数リテラル 200806L に展開されます。
(マクロ定数)
__cpp_inline_variables
整数リテラル 201606L に展開されます。
(マクロ定数)
__cpp_lambdas
整数リテラル 200907L に展開されます。
(マクロ定数)
__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_variable_templates
整数リテラル 201304L に展開されます。
(マクロ定数)
__cpp_variadic_templates
整数リテラル 200704L に展開されます。
(マクロ定数)
__cpp_variadic_using
整数リテラル 201611L に展開されます。
(マクロ定数)
(C++20およびそれ以降)

[編集]

#include <iostream>
 
//make function factory and use it
#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'
 
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);               //note the lack of quotes
}

出力:

abcd: 12
fff: 2
qqq: 23
34
output: million

[編集] 関連項目

テキストマクロの置換C言語リファレンス