gpt4 book ai didi

c++ - 将多个参数作为单个宏参数传递

转载 作者:太空狗 更新时间:2023-10-29 21:21:56 24 4
gpt4 key购买 nike

问题

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

#define make_string(x) #x

int a , b;
const char my_string[] = make_string( a + b ); //my_string holds "a + b"

有什么方法可以进行逆过程吗?
我的意思是,获取原始字符串并将其转换为一系列标记。例如(~# 是执行此操作的理论预处理器运算符):

#define make_tokens(x) ~#x

int a = 0 , b = 1;
int c = make_tokens( "a + b" ); //c holds 1 (The result of a + b addition)

一些上下文(或者“我正在解决 XY 问题?”)

我正在编写一个模板元编程库,它在很大程度上基于定义元函数并专门化它们以获得不同的行为(如函数重载)。
例如:

//Metafunction declaration:
template<typename T , typename U>
struct better_type;


//Metafunction specialization (overload)
template<>
struct better_type<char,unsigned char>
{
using result = char;
};

库假定元函数是任何带有 result 的模板。公共(public)别名。所以用户必须执行常见的 typename function</*function argumments*/>::result得到函数的结果。

为避免这种情况,我利用了 C++11 模板别名并将函数定义为两部分:

  • 函数实现:实现功能的上述形式的元函数。

    template<typename T>
    struct function_impl;

    为了实现(重载)他自己的函数版本,用户特化了这个模板:

    template<>
    struct function_impl<bool>
    {
    using result = /* something */;
    };
  • 函数声明:为用户定义函数接口(interface)。它只是真正的元函数的别名。

    template<typename T>
    using function = typename function_impl<T>::result;

所以函数声明总是一对声明:函数实现和用户界面别名。

现在我的目标是使用 CPP 在一些通用的 whay 中自动进行声明。像这样的东西:

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

可以用作:

define_function( typename T , my_function , T );

并毫无问题地生成以下代码:

template< typename T >
struct mi_function_impl;

template< typename T >
using mi_function = typename my_function_impl< T >::type;

但请考虑其他用法示例:

define_function( typename T , typename U , mi_binary_function , T , U );

当然typename T , typename U旨在成为第一个宏参数,T , U第二个。但这行不通,因为它们被视为五个不同的宏参数。
这就是为什么我在考虑 token 生成,因为有了这个功能,宏可以重新编写为:

#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

并且多个参数将作为生成预期结果的唯一原始字符串传递:

define_function( "typename T , typename U" , mi_binary_function , "T , U" );

最佳答案

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 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)

关于c++ - 将多个参数作为单个宏参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21649088/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com