问题描述
考虑以下code:
template<typename T0>
void send( const std::string& func, const T0& t0 )
{
std::ostringstream s;
s << func << ": " << t0;
sendMessage( s.str() );
}
template<typename T0, typename T1>
void send( const std::string& func, const T0& t0, const T1& t1 )
{
std::ostringstream s;
s << func << ": " << t0 << "," << t1;
sendMessage( s.str() );
}
template<typename T0, typename T1, typename T2>
void send( const std::string& func, const T0& t0, const T1& t1, const T2& t2 )
{
std::ostringstream s;
s << func << ": " << t0 << "," << t1 << "," << t2;
sendMessage( s.str() );
}
等等......
etc...
我需要这份长达像15的参数。
I need this up to something like 15 arguments.
我只是想知道是否有可能使用升压。preprocessor简化这种重复,如何我会去了解它。我通过文档看了,但它是相当混乱的。
I'm just wondering if it's possible to use Boost.Preprocessor to simplify this repetition, and how I would go about it. I looked through the docs but it's fairly confusing.
推荐答案
升压preprocessor
可以做这样的东西,你可以在这里有血统教程:
boost.preprocessor
can do this kind of stuff and you can have descent tutorial here: Intro to preprocessor metaprogramming
有关您的具体的例子这里是我想出了(注意code:我只是跑它的preprocessor下,检查结果code是我所期望的,但没有尝试编译在code本身)。
For your specific example here's the code I came up with (note: I just ran it under the preprocessor to check that the resulting code was what I would expect but did not try to compile the code itself).
这同时使用 enum_params
宏,帮助生成的属性列表和 local_iterate
,允许扩大与宏各种说法。我也有,如果与处理您的特殊情况宏:VS,发送到您的流的第一个参数
This uses both the enum_params
macro that helps generate list of attributes and local_iterate
that allow to expand a macro with a range of argument. I have also a macro if to handle your special case with ": " vs "," for the first argument sent to your stream.
总之,当你开始了解如何升压preprocessor
工作找你在的变得相对容易和它的合理的更换,直到可变参数模板上受支持大多数编译器。确实注意到,虽然这是在编译时非常密集,所以请谨慎使用。
Overall when you start to understand how boost.preprocessor
work searching for the feature you need in its reference manual becomes relatively easy and its a "reasonable" replacement until variadic templates are supported by most compilers. Do note though that it is very intensive at compilation time, so use with caution.
编辑:虽然我没有认为这是一个比较简单的例子,一般的练习,我不同意,虽然在使用伪流类通过synek317的建议将是一个更加灵活,轻量级这个具体的例子编码项解。再次实施此类流不要求你做的所有运营商的专业化,事实上提振再次提供输入输出流库,帮助你实现一个类作为一个标准的C ++流(的)
edit: While I did consider this as a general exercise with a relatively simple example I do agree though that in term of coding for this specific example using a pseudo stream class as suggested by synek317 would be a more flexible and "lightweight" solution. Again implementing such stream do not require you to do the specialization of all the operators and in fact boost again provide the IOStreams library to help you implement a class as a standard C++ stream (http://www.boost.org/doc/libs/1_52_0/libs/iostreams/doc/index.html)
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/control/if.hpp>
# ifndef MY_SEND_MAX
# define MY_SEND_MAX 15
# endif
/*
* macros called through BOOST_PP_REPEAT to generate lists
* J : I don't know what it is
* I : the current counter number
* D : the 3rd argument of BOOST_PP_REPEAT
*/
// Generate the list of arguments after std::string
# define MY_SEND_PARAM(J,I,D) , BOOST_PP_CAT(const T,I) & BOOST_PP_CAT(arg,I)
// Generate the stream's <<s adter the string
# define MY_SEND_STREAM(J,I,D) <<BOOST_PP_IF(I,",",": ")<<BOOST_PP_CAT(arg,I)
/*
* Macro to call for generating onde function
* N : the number of arguments
*/
// Create one function with a string and N extra aarguments
# define MY_SEND(N) \
template<BOOST_PP_ENUM_PARAMS(N,typename T)> \
void send(std::string const &fn BOOST_PP_REPEAT(N,MY_SEND_PARAM,~)) { \
std::ostringstream s; \
s<<fn BOOST_PP_REPEAT(N,MY_SEND_STREAM,~); \
sendMessage(s.str()); \
}
// End of my macro
/*
* BOOST_PP local loop to generate all the the function
*/
// What macro to call in the loop
#define BOOST_PP_LOCAL_MACRO(n) MY_SEND(n)
// do the job form 0 to MY_SEND_MAX
#define BOOST_PP_LOCAL_LIMITS (0,MY_SEND_MAX)
// execute the loop
#include BOOST_PP_LOCAL_ITERATE()
// undefine all my stuff
# undef MY_SEND_PARAM
# undef MY_SEND_STREAM
# undef MY_SEND
# undef BOOST_PP_LOCAL_MACRO
# undef BOOST_PP_LOCAL_LIMITS
这篇关于使用Boost。preprocessor减少这种code repitition的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!