例如
DECL_TYPE(a) becomes decltype(a)
DECL_TYPE(a, b) becomes decltype(a), decltype(b)
DECL_TYPE(a, b, c) becomes decltype(a), decltype(b), decltype(c)
如何定义宏DECL_TYPE
?
答案 0 :(得分:1)
好吧,让我们从计算参数数量的基本问题开始。
可以这样:
nargs.h 的#pragma once
// Copyright (c) 2013 Alf P. Steinbach.
//
// The MM_NARGS macro evaluates to the number of arguments that have been
// passed to it.
//
// Based on original code by Laurent Deniau,
// "__VA_NARG__," 17 January 2006, <comp.std.c> (29 November 2007).
// https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/d-6Mj5Lko_s
#include <rfc/macro_magic/invoke.h> // MM_INVOKE
#include <rfc/macro_magic/concat.h> // MM_CONCAT
#define MM_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define MM_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
#ifdef MM_USE_ORIGINAL_DEFINITION
#define MM_NARGS_(...) MM_ARG_N( __VA_ARGS__ )
#define MM_NARGS( ...) MM_NARGS_( __VA_ARGS__, MM_RSEQ_N() )
#else
#define MM_NARGS_AUX( ... ) MM_INVOKE( MM_ARG_N, ( __VA_ARGS__ ) )
#define MM_NARGS( ... ) MM_NARGS_AUX( __VA_ARGS__, MM_RSEQ_N() )
#endif
...使用这两个辅助文件:
invoke.h 的#pragma once
// Copyright (c) 2013 Alf P. Steinbach.
#define MM_INVOKE( macro, args ) macro args
#define MM_INVOKE_B( macro, args ) macro args // For nested invocation with g++.
concat.h 的
#pragma once
// Copyright (c) 2013 Alf P. Steinbach.
#define MM_CONCAT__( a, b ) a ## b
#define MM_CONCAT_( a, b ) MM_CONCAT__( a, b )
#define MM_CONCAT( a, b ) MM_CONCAT_( a, b )
自从我摆弄这段代码以来已经有一段时间了,我似乎回想起串联问题。但至少存在上述代码有效的上下文。 可能一般都有效。
宏将一个给定的宏应用于一系列参数:
apply.h 的#pragma once
// Copyright (c) 2013 Alf P. Steinbach.
#include <rfc/macro_magic/nargs.h> // MM_INVOKE, MM_INVOKE_B, MM_CONCAT, MM_NARGS
#define MM_APPLY_1( macroname, a1 ) \
MM_INVOKE_B( macroname, (a1) )
#define MM_APPLY_2( macroname, a1, a2 ) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_1( macroname, a2 )
#define MM_APPLY_3( macroname, a1, a2, a3 ) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_2( macroname, a2, a3 )
#define MM_APPLY_4( macroname, a1, a2, a3, a4 ) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_3( macroname, a2, a3, a4 )
#define MM_APPLY_5( macroname, a1, a2, a3, a4, a5 ) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_4( macroname, a2, a3, a4, a5 )
#define MM_APPLY_6( macroname, a1, a2, a3, a4, a5, a6 ) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_5( macroname, a2, a3, a4, a5, a6 )
#define MM_APPLY_7( macroname, a1, a2, a3, a4, a5, a6, a7 ) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_6( macroname, a2, a3, a4, a5, a6, a7 )
#define MM_APPLY_8( macroname, a1, a2, a3, a4, a5, a6, a7, a8 ) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_7( macroname, a2, a3, a4, a5, a6, a7, a8 )
#define MM_APPLY_9( macroname, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_8( macroname, a2, a3, a4, a5, a6, a7, a8, a9 )
#define MM_APPLY_10( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_9( macroname, a2, a3, a4, a5, a6, a7, a8, a9, a10 )
#define MM_APPLY_11( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_10( macroname, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 )
#define MM_APPLY_12( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_11( macroname, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 )
#define MM_APPLY_13( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12, a13 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_12( macroname, \
a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, \
a12, a13 \
)
#define MM_APPLY_14( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12, a13, a14 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_13( macroname, \
a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, \
a12, a13, a14 \
)
#define MM_APPLY_15( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12, a13, a14, a15 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_14( macroname, \
a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, \
a12, a13, a14, a15 \
)
#define MM_APPLY_16( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12, a13, a14, a15, a16 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_15( macroname, \
a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, \
a12, a13, a14, a15, a16 \
)
#define MM_APPLY_17( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12, a13, a14, a15, a16, a17 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_16( macroname, \
a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, \
a12, a13, a14, a15, a16, a17 \
)
#define MM_APPLY_18( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12, a13, a14, a15, a16, a17, a18 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_17( macroname, \
a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, \
a12, a13, a14, a15, a16, a17, a18 \
)
#define MM_APPLY_19( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12, a13, a14, a15, a16, a17, a18, a19 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_18( macroname, \
a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, \
a12, a13, a14, a15, a16, a17, a18, a19 \
)
#define MM_APPLY_20( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_19( macroname, \
a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, \
a12, a13, a14, a15, a16, a17, a18, a19, a20 \
)
#define MM_APPLY_21( macroname, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, \
a21 \
) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_20( macroname, \
a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, \
a12, a13, a14, a15, a16, a17, a18, a19, a20, a21 \
)
#define MM_APPLY( macroname, ... ) \
MM_INVOKE( \
MM_CONCAT( MM_APPLY_, MM_NARGS( __VA_ARGS__ ) ), \
( macroname, __VA_ARGS__ ) \
)
现在不是那么好。
这么少的重复。
示例用例:
#ifdef _WIN32
namespace cppx{ typedef wchar_t Raw_syschar; } // Implies UTF-16 encoding.
# define CPPX_SYSCHAR_IS_WIDE 1
# define CPPX_WITH_SYSCHAR_PREFIX_( lit ) L##lit
#else
namespace cppx{ typedef char Raw_syschar; } // Implies UTF-8 encoding.
# define CPPX_SYSCHAR_IS_WIDE 0
# define CPPX_WITH_SYSCHAR_PREFIX_( lit ) lit
#endif
#define CPPX_WITH_SYSCHAR_PREFIX( ... ) \
MM_APPLY( CPPX_WITH_SYSCHAR_PREFIX_, __VA_ARGS__ )
#define CPPX_AS_SYSCHAR( ... ) \
::cppx::typed( CPPX_WITH_SYSCHAR_PREFIX( __VA_ARGS__ ) )
#define CPPX_U CPPX_AS_SYSCHAR
#define CPPX_RAW_U CPPX_WITH_SYSCHAR_PREFIX
允许一个人写例如。
auto const x = CPPX_U
(
"First line\n",
"Second line"
);
并将其翻译为
auto const x = cppx::typed( L"First line\n" L"Second line" );
在您的特定示例中,您将定义类似
的代码#define APPLY_DECL_TYPE( x ) decltype( x ),
#define DECL_TYPE( ... ) MM_APPLY( APPLY_DECL_TYPE, __VA_ARGS__ )
你提供的上下文太少,无法决定在最后一次争论之后处理逗号(或缺少逗号)的正确策略。
但我认为这应该足以让你走上正确(或工作)的轨道。
最后想到,听起来好像使用 可变参数模板 而非宏来解决问题。宏是针对那些无法处理的情况,如上面显示的字符串文字示例。但同样,你提供的上下文太少了。