如何为每个宏参数声明类型?

时间:2014-12-09 04:43:46

标签: c++ macros

例如

 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

1 个答案:

答案 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__ )

你提供的上下文太少,无法决定在最后一次争论之后处理逗号(或缺少逗号)的正确策略。

但我认为这应该足以让你走上正确(或工作)的轨道。

最后想到,听起来好像使用 可变参数模板 而非宏来解决问题。宏是针对那些无法处理的情况,如上面显示的字符串文字示例。但同样,你提供的上下文太少了。