C++ 作为单个宏参数传递多个参数 问题

C++ 作为单个宏参数传递多个参数 问题,c++,c++11,macros,template-meta-programming,C++,C++11,Macros,Template Meta Programming,C预处理器具有#,它将在其后编写的任何表达式转换为原始字符串。例如: #define make_string(x) #x int a , b; const char my_string[] = make_string( a + b ); //my_string holds "a + b" //Metafunction declaration: template<typename T , typename U> struct better_type; //Metafunctio

C预处理器具有
#
,它将在其后编写的任何表达式转换为原始字符串。例如:

#define make_string(x) #x

int a , b;
const char my_string[] = make_string( a + b ); //my_string holds "a + b"
//Metafunction declaration:
template<typename T , typename U>
struct better_type;


//Metafunction specialization (overload)
template<>
struct better_type<char,unsigned char>
{
    using result = char;
};
有没有办法执行反向过程?
我的意思是,获取一个原始字符串并将其转换为一系列令牌。例如(
~#
是执行此操作的理论预处理器操作符):

一些上下文(或“我在XY问题上摔倒了?”) 我正在编写一个模板元编程库,它主要基于定义元函数并对它们进行专门化以获得不同的行为(如函数重载)。
例如:

#define make_string(x) #x

int a , b;
const char my_string[] = make_string( a + b ); //my_string holds "a + b"
//Metafunction declaration:
template<typename T , typename U>
struct better_type;


//Metafunction specialization (overload)
template<>
struct better_type<char,unsigned char>
{
    using result = char;
};
为了实现(重载)自己版本的函数,用户专门使用此模板:

template<>
struct function_impl<bool>
{
    using result = /* something */;
};
并毫无问题地生成以下代码:

template< typename T >
struct mi_function_impl;

template< typename T >
using mi_function = typename my_function_impl< T >::type;
当然,
typename T,typename U
是第一个宏参数,
T,U
是第二个宏参数。但这不起作用,因为它们被视为五个不同的宏参数。
这就是我考虑生成令牌的原因,因为有了该功能,宏可以重新连接为:

#define define_function( template_args , function_name , function_args ) \
        template< make_tokens(template_args) >                           \
        struct function_name##_impl;                                     \
                                                                         \
        template< template_args >                                        \
        using function_name = typename function_name##_impl< make_tokens(function_args) >::type

X/Y问题的解决方案是使用括号而不是引号:

define_function( (typename T, typename U) , mi_binary_function , (T, U) );
// yields:
template< typename T, typename U > struct mi_binary_function_impl; template< typename T, typename U > using mi_binary_function = typename mi_binary_function_impl < T, U >::type;
define_函数((typename T,typename U),mi_二进制_函数(T,U));
//收益率:
模板struct mi\U binary\U function\U impl;模板使用mi_binary_函数=typename mi_binary_函数\U impl::type;
可实施为:

#define strip_parens(...) __VA_ARGS__

#define define_function( template_args , function_name , function_args ) \
    template< strip_parens template_args >                               \
    struct function_name##_impl;                                         \
                                                                         \
    template< strip_parens template_args >                               \
    using function_name = typename function_name##_impl                  \
                                   < strip_parens function_args >::type  // end
#define gen_single_param_name(number_plus_2)                    \
    BOOST_PP_CAT(T, BOOST_PP_DEC(BOOST_PP_DEC(number_plus_2)))  // end

#define gen_single_param(s, data, elem) elem gen_single_param_name(s)
#define gen_params_from_seq(seq) BOOST_PP_SEQ_TRANSFORM(gen_single_param, _, seq)

#define gen_single_arg(s, data, elem) gen_single_param_name(s)
#define gen_args_from_seq(seq) BOOST_PP_SEQ_TRANSFORM(gen_single_arg, _, seq)

#define define_function_impl(name, param_seq, arg_seq)                    \
    template< BOOST_PP_SEQ_ENUM(param_seq) >                              \
    struct name ## _impl;                                                 \
                                                                          \
    template< BOOST_PP_SEQ_ENUM(param_seq) >                              \
    using name = typename name ## _impl                                   \
                 < BOOST_PP_SEQ_ENUM(arg_seq) > :: result                 // end

#define define_function_seq(name, param_seq)                    \
    define_function_impl(name, gen_params_from_seq(param_seq),  \
                         gen_args_from_seq(param_seq))          // end

#define define_function(name, param_list) \
    define_function_seq(name, BOOST_PP_VARIADIC_TO_SEQ param_list)
#定义带参数(…)(变量)__
#定义函数(模板参数、函数名称、函数参数)\
模板\
结构函数_name###u impl\
\
模板\
使用函数名=类型名函数名\
:类型//结束

但是,我们也可以自动生成参数名(无论如何,在专门化中为它们指定新名称):

define_函数(foo,(class,int,typename));
//收益率:
模板struct foo_impl;使用foo=typename foo_impl的模板:结果;
可实施为:

#define strip_parens(...) __VA_ARGS__

#define define_function( template_args , function_name , function_args ) \
    template< strip_parens template_args >                               \
    struct function_name##_impl;                                         \
                                                                         \
    template< strip_parens template_args >                               \
    using function_name = typename function_name##_impl                  \
                                   < strip_parens function_args >::type  // end
#define gen_single_param_name(number_plus_2)                    \
    BOOST_PP_CAT(T, BOOST_PP_DEC(BOOST_PP_DEC(number_plus_2)))  // end

#define gen_single_param(s, data, elem) elem gen_single_param_name(s)
#define gen_params_from_seq(seq) BOOST_PP_SEQ_TRANSFORM(gen_single_param, _, seq)

#define gen_single_arg(s, data, elem) gen_single_param_name(s)
#define gen_args_from_seq(seq) BOOST_PP_SEQ_TRANSFORM(gen_single_arg, _, seq)

#define define_function_impl(name, param_seq, arg_seq)                    \
    template< BOOST_PP_SEQ_ENUM(param_seq) >                              \
    struct name ## _impl;                                                 \
                                                                          \
    template< BOOST_PP_SEQ_ENUM(param_seq) >                              \
    using name = typename name ## _impl                                   \
                 < BOOST_PP_SEQ_ENUM(arg_seq) > :: result                 // end

#define define_function_seq(name, param_seq)                    \
    define_function_impl(name, gen_params_from_seq(param_seq),  \
                         gen_args_from_seq(param_seq))          // end

#define define_function(name, param_list) \
    define_function_seq(name, BOOST_PP_VARIADIC_TO_SEQ param_list)
#定义发电机单参数名称(数字加2)\
BOOST_PP_CAT(T,BOOST_PP_DEC(BOOST_PP_DEC(数字加2))//结束
#定义gen_single_参数、数据、元素元素gen_single_参数名称
#从顺序(seq)BOOST\u PP\u seq\u TRANSFORM(gen\u single\u param,seq)定义gen\u参数
#定义gen_single_参数、数据、元素gen_single_参数名称
#从顺序(seq)BOOST\u PP\u seq\u TRANSFORM(单次参数,顺序)定义gen\u args\u
#定义函数(名称、参数、参数)\
模板\
结构名称###u impl\
\
模板\
using name=typename name###u impl\
::结果//结束
#定义函数(名称、参数)\
定义函数impl(名称,gen_params_from_seq(param seq))\
gen_args_from_seq(param_seq))//结束
#定义函数(名称、参数列表)\
定义函数顺序(名称、变量到顺序参数列表)

你试过(我没有试过,所以我没有写答案):
定义函数((typename t,typename U),mi_二进制函数,(t,U)
?这可能更容易处理。@Matstpeterson这不起作用,因为预处理器只接受参数并将其放入
中,所以得到的是无效语法
模板
,我一直在想,然后用第二个宏去掉多余的括号。我100%确定这一点无法从宏参数中删除双引号。@Matstpeterson它不是有点像
#define strip(…)(uu VA_ARGS)
,通过
#define define函数(A,B,C)模板结构B###U impl;
?还有
define函数(typename t COMMA typename U,…)的选项(当然很难看)
。这是一个宏参数,即使
COMMA
是一个扩展到
的宏。我不确定
s
参数有多稳定。您可能需要稍微解决一下,但我们这里需要的唯一保证是它可以用于为序列中的每个元素创建唯一标识符。
BOOST\u PP_DEC实际上不是必需的。顺便说一句。在coliru的boost版本和clang++版本中,
boost\u PP\u VARIADIC\u TO_SEQ
似乎出现了问题。我以前遇到过这个问题。boost解决方案看起来很棒。谢谢。我只是想知道是否有更简单的方法来生成模板参数。我不想依赖任何外部环境l依赖项,包括Boost。顺便说一句,我可以检查Boost::预处理器的实现,并得到我需要的。但我认为这就像重新发明轮子一样。
define_function( (typename T, typename U) , mi_binary_function , (T, U) );
// yields:
template< typename T, typename U > struct mi_binary_function_impl; template< typename T, typename U > using mi_binary_function = typename mi_binary_function_impl < T, U >::type;
#define strip_parens(...) __VA_ARGS__

#define define_function( template_args , function_name , function_args ) \
    template< strip_parens template_args >                               \
    struct function_name##_impl;                                         \
                                                                         \
    template< strip_parens template_args >                               \
    using function_name = typename function_name##_impl                  \
                                   < strip_parens function_args >::type  // end
define_function(foo, (class, int, typename));
// yields:
template< class T0, int T1, typename T2 > struct foo_impl; template< class T0, int T1, typename T2 > using foo = typename foo_impl < T0, T1, T2 > :: result;
#define gen_single_param_name(number_plus_2)                    \
    BOOST_PP_CAT(T, BOOST_PP_DEC(BOOST_PP_DEC(number_plus_2)))  // end

#define gen_single_param(s, data, elem) elem gen_single_param_name(s)
#define gen_params_from_seq(seq) BOOST_PP_SEQ_TRANSFORM(gen_single_param, _, seq)

#define gen_single_arg(s, data, elem) gen_single_param_name(s)
#define gen_args_from_seq(seq) BOOST_PP_SEQ_TRANSFORM(gen_single_arg, _, seq)

#define define_function_impl(name, param_seq, arg_seq)                    \
    template< BOOST_PP_SEQ_ENUM(param_seq) >                              \
    struct name ## _impl;                                                 \
                                                                          \
    template< BOOST_PP_SEQ_ENUM(param_seq) >                              \
    using name = typename name ## _impl                                   \
                 < BOOST_PP_SEQ_ENUM(arg_seq) > :: result                 // end

#define define_function_seq(name, param_seq)                    \
    define_function_impl(name, gen_params_from_seq(param_seq),  \
                         gen_args_from_seq(param_seq))          // end

#define define_function(name, param_list) \
    define_function_seq(name, BOOST_PP_VARIADIC_TO_SEQ param_list)