Boost Preprocessorでコンストラクタ生成
今回は、下記のように記述すると、その下のコードのように展開してくれるマクロを、Boost Preprocessorを利用して作成してみたいと思います。(実際には改行は生成されません。)
struct Person { std::string FirstName; std::string LastName; int Age; CONSTRUCTOR(Person, FirstName, LastName, Age) };
struct Person { std::string FirstName; std::string LastName; int Age; Person(decltype(FirstName) a_FirstName, decltype(LastName) a_LastName, decltype(Age) a_Age) : FirstName(std::move(a_FirstName)), LastName(std::move(a_LastName)), Age(std::move(a_Age)) {} };
マクロ定義
Variadic引数をSEQに変換し、各要素をBOOST_PP_SEQ_TRANSFORMで変換したのちBOOST_PP_SEQ_ENUMで出力しています。(BOOST_PP_SEQ_ENUMはカンマ区切りで出力されます。)
通常のマクロでは結合はa_##memberのように記述しますが、Boost Preprocessorを利用している場合はBOOST_PP_CATを利用します。(同様に#memberはBOOST_PP_STRINGIZE(member)と記述します。)
#include <boost\preprocessor.hpp> #define _CONSTRUCTOR_PARAM(s, data, member) \ decltype(member) BOOST_PP_CAT(a_, member) #define _CONSTRUCTOR_PARAMS(members) \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(_CONSTRUCTOR_PARAM, , members)) #define _CONSTRUCTOR_INIT(s, data, member) \ member(std::move(BOOST_PP_CAT(a_, member))) #define _CONSTRUCTOR_INITS(members) \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(_CONSTRUCTOR_INIT, , members)) #define _CONSTRUCTOR(cls, members) \ cls(_CONSTRUCTOR_PARAMS(members)) : _CONSTRUCTOR_INITS(members) {} #define CONSTRUCTOR(cls, ...) \ _CONSTRUCTOR(cls, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
展開結果の確認
cppファイルのプロパティで、Process to a Fileを有効化してファイルをコンパイルすると、出力フォルダに .i ファイルが生成されます。(.objファイルが出力されなくなるため、ビルド時には無効化してください。)