簡體   English   中英

使用宏從__VA_ARGS__生成參數列表

[英]Using macros to generate argument list from __VA_ARGS__

僅出於一點背景,這不是一件小事! 我正在使用Boost.Python,並且為了避免出現許多難看的樣板代碼,我使用宏在Python包裝器類中包裝函數,以選擇調用該方法的Python覆蓋(如果存在)。

我將難題歸結為最簡單的形式, 在這里

#include <iostream>

using namespace std;

void foo() { cout << "foo" << endl; }
void bar(char, short, int) { cout <<"bar" << endl; }

#define DEFINE_FUNCTION_WRAPPER(return_type, name, ...)\
return_type name##_wrapper(/* macro expansion */)\
{\
    return name(/* macro expansion */);\
}\

DEFINE_FUNCTION_WRAPPER(void, foo)  // works!
//DEFINE_FUNCTION_WRAPPER(void, foo, char, short, int)  // knowledge insufficient

int main() {
    foo_wrapper();
    //bar_wrapper(0, 1, 2);
}

雖然這顯然適用於foo ,但我的目標是讓DEFINE_FUNCTION_WRAPPER(void, foo, char, short, int)生成如下所示的函數包裝:

void bar_wrapper(char _1, short _2, int _3)
{
    return bar(_1, _2, _3);
}

我希望針對如何最好地解決此問題指明正確的方向,因為我真的很想掌握這種宏魔術。

任何幫助表示贊賞!

注意:我正在針對MSVC C ++ 11進行編譯。

假設您確實需要宏(我對Boost.Python不太熟悉,但是可變參數模板和完美轉發與此相同,並且在適用時更加干凈),可以使用幾個便捷的Boost。預處理器工具。

要注意的是,宏末尾的省略號必須在其位置傳遞至少一個參數。 它不能為零。 為了解決這個問題,您必須在整個過程中的某個位置放棄至少一個參數名稱。 我選擇讓宏根據是否獲取任何參數相關的參數來填充該省略號,從而選擇其他兩個宏之一。

#include <boost/preprocessor.hpp>

//generate "type _#"
#define PARAMS(z,n,data) BOOST_PP_TUPLE_ELEM(n,data) _##n

//The first variant: with parameters
//parameters: PARAMS(z,0,(char,short,int)), PARAMS(z,1,(char,short,int)), PARAMS(z,2,(char,short,int))
//call: _0, _1, _2

#define DEFINE_FUNCTION_WRAPPER_WITH_PARAMS(return_type, name, ...)\
return_type name##_wrapper(BOOST_PP_ENUM(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), PARAMS, (__VA_ARGS__)))\
{\
    return name(BOOST_PP_ENUM_PARAMS(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), _));\
}

//The second variant: no parameters
#define DEFINE_FUNCTION_WRAPPER_WITHOUT_PARAMS(return_type, name)\
return_type name##_wrapper()\
{\
    return name();\
}

//choose variant based on whether more than two arguments are passed
#define DEFINE_FUNCTION_WRAPPER(...)\
    BOOST_PP_IF(\
        BOOST_PP_GREATER(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 2), \
        DEFINE_FUNCTION_WRAPPER_WITH_PARAMS,\
        DEFINE_FUNCTION_WRAPPER_WITHOUT_PARAMS\
    )(__VA_ARGS__)

//Clang output:
//void foo_wrapper( char _0 , short _1 , int _2){ return foo( _0 , _1 , _2);}
//int bar_wrapper(){ return bar();}

BOOST_PP_ENUM用遞增的數字調用給定的宏,我們在PARAMS宏中使用它作為類型(傳入數據)和名稱元組的索引。 它還將逗號放在擴展之間,但不要在最后一個之后。 您可以在代碼注釋中看到它的擴展。 如果需要,可以忽略z

BOOST_PP_ENUM_PARAMS保存單獨的宏的工作,而是使用“常量”將數字附加到其后。 也將逗號放在擴展之間。 我們使用下划線以_0,_1,_2結尾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM