在可变参数宏中分配参数

时间:2015-01-04 12:16:14

标签: c++ c c-preprocessor variadic-macros

我想构造一个宏,它接受可变数量的参数,并以类似于下面示例的格式将第一个参数分配给每个后续参数:

Call:   MACRO(F,A)
Result: F:A

Call:   MACRO(F,A,B,C)
Result: F:A F:B F:C

我已经看到https://github.com/swansontec/map-macro和递归的一般概念解决方法:

#define EVAL0(...) __VA_ARGS__
#define EVAL1(...) EVAL0 (EVAL0 (EVAL0 (__VA_ARGS__)))
#define EVAL2(...) EVAL1 (EVAL1 (EVAL1 (__VA_ARGS__)))
#define EVAL3(...) EVAL2 (EVAL2 (EVAL2 (__VA_ARGS__)))
#define EVAL4(...) EVAL3 (EVAL3 (EVAL3 (__VA_ARGS__)))
#define EVAL(...)  EVAL4 (EVAL4 (EVAL4 (__VA_ARGS__)))

但我无法理解如何将此问题应用于我的问题。任何人都可以提供一个例子来实现上面显示的结果吗?谢谢!

3 个答案:

答案 0 :(得分:6)

使用Boost.PP:

#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>

#define TRANSFORM(r, data, elem) data:elem

#define MACRO(F, ...) \
    BOOST_PP_SEQ_FOR_EACH(TRANSFORM, F, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))

Demo。这将(AFAIR)最多可以处理255个参数。

答案 1 :(得分:4)

您可以使用NARGS宏来计算可变参数宏的参数,以创建递归宏,为您的所有aguments应用前缀:

#define NARGS(...) NARGS_(__VA_ARGS__, 5, 4, 3, 2, 1, 0)
#define NARGS_(_5, _4, _3, _2, _1, N, ...) N

#define CONC(A, B) CONC_(A, B)
#define CONC_(A, B) A##B

#define PREFIX_0(P, E) E
#define PREFIX_1(P, E) P:E
#define PREFIX_2(P, E, ...) P:E PREFIX_1(P, __VA_ARGS__)
#define PREFIX_3(P, E, ...) P:E PREFIX_2(P, __VA_ARGS__)
#define PREFIX_4(P, E, ...) P:E PREFIX_3(P, __VA_ARGS__)
#define PREFIX_5(P, E, ...) P:E PREFIX_4(P, __VA_ARGS__)

#define PREFIX(P, ...) CONC(PREFIX_, NARGS(__VA_ARGS__)) (P, __VA_ARGS__)

PREFIX(F, A)
PREFIX(F, A, B, C, D)

为简洁起见,参数总数限制为5,但您可以通过以明显的方式扩展NARGSNARGS_以及撰写更多PREFIX_X来扩展此解决方案宏。

答案 2 :(得分:0)

您可以将自己的宏传递给MAP宏:

示例

#include<iostream>

struct F {
    static void A() { std::cout << "A\n"; }
    static void B() { std::cout << "B\n"; }
    static void C() { std::cout << "C\n"; }
};

int main()
{
    #define CALL_MEMBER(Member) F::Member();
    #define CALL_STRUCTURE(Structure) Structure::CALL_MEMBER
    #define MACRO(Structure, ...)  MAP(CALL_STRUCTURE(Structure), __VA_ARGS__)
    MACRO(F, A)
    MACRO(F, A, B, C)
}

来自https://github.com/swansontec/map-macro

的MAP宏
/*
* Copyright (C) 2012 William Swanson
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the names of the authors or
* their institutions shall not be used in advertising or otherwise to
* promote the sale, use or other dealings in this Software without
* prior written authorization from the authors.
*/
#ifndef MAP_H_INCLUDED
#define MAP_H_INCLUDED
#define EVAL0(...) __VA_ARGS__
#define EVAL1(...) EVAL0 (EVAL0 (EVAL0 (__VA_ARGS__)))
#define EVAL2(...) EVAL1 (EVAL1 (EVAL1 (__VA_ARGS__)))
#define EVAL3(...) EVAL2 (EVAL2 (EVAL2 (__VA_ARGS__)))
#define EVAL4(...) EVAL3 (EVAL3 (EVAL3 (__VA_ARGS__)))
#define EVAL(...) EVAL4 (EVAL4 (EVAL4 (__VA_ARGS__)))
#define MAP_END(...)
#define MAP_OUT
#define MAP_GET_END() 0, MAP_END
#define MAP_NEXT0(test, next, ...) next MAP_OUT
#define MAP_NEXT1(test, next) MAP_NEXT0 (test, next, 0)
#define MAP_NEXT(test, next) MAP_NEXT1 (MAP_GET_END test, next)
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__)
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__)
#define MAP(f, ...) EVAL (MAP1 (f, __VA_ARGS__, (), 0))
#endif