gcc(g++)5以降では、C言語スタイルの可変引数リスト(...
)に非PODクラス型(≒普通のC++クラス型)を渡すことができる。
注意:この振る舞いはgcc 5以降という特定の処理系でのみ合法であり*1、またC++の型システムを無視するため、強い理由がない限りは利用しないこと。
#include <cstdio> #include <cstdarg> // 非POD型 struct X { X() { std::puts("ctor"); } ~X() { std::puts("dtor"); } X(const X&) { std::puts("copy"); } X& operator=(const X&) { std::puts("copy"); return *this; } }; void f(int n, ...) { va_list ap; va_start(ap, n); X x = va_arg(ap, X); // OK(conditionally-supported) va_end(ap); } int main() { X x; f(0, x); // OK(conditionally-supported) }
-Wconditionally-supported
オプションを指定しない限り、上記コードは警告なしに正常にコンパイルされる*2。関数実装でva_list
を介して実引数にアクセスする際は、va_arg
マクロに型名(上記コードではX
)を指定する。
C++11
可変引数リストと非PODクラス型の関係
可変引数リストに非自明なコピー/ムーブコンストラクタまたは非自明なデストラクタをもつクラス型を渡した場合、処理系によってはサポートされ(conditionally-supported)、そのセマンティクスは処理系定義(implementation-defined)となる。N3337 1.3.5, 5.2.2/7より一部引用。
(省略)
gcc 5.4ドキュメントより該当箇所を引用。
Whether an argument of class type with a non-trivial copy constructor or destructor can be passed to ... (C++0x 5.2.2).
5.1 Conditionally-Supported Behavior
Such argument passing is supported, using the same pass-by-invisible-reference approach used for normal function arguments of such types.
関連URL