使用 Boost.Preprocessor 减少此代码重复

Ger*_*ald 3 c++ boost boost-preprocessor

考虑以下代码:

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() );
}
Run Code Online (Sandbox Code Playgroud)

等等...

我需要最多 15 个参数。

我只是想知道是否可以使用 Boost.Preprocessor 来简化这种重复,以及我将如何去做。我查看了文档,但它相当令人困惑。

Fre*_* Py 5

boost.preprocessor可以做这种事情,你可以在这里有下降教程:预处理器元编程简介

对于您的具体示例,这是我想出的代码(注意:我只是在预处理器下运行它以检查生成的代码是否符合我的预期,但没有尝试编译代码本身)。

这既使用了enum_params帮助生成属性列表的宏,又使用local_iterate了允许扩展具有参数范围的宏。我还有一个宏 if 用 ":" vs "," 处理你的特殊情况,作为发送到你的流的第一个参数。

总体而言,当您开始了解boost.preprocessor参考手册中搜索所需功能的工作如何变得相对容易,并且在大多数编译器支持可变参数模板之前,它是“合理的”替代品。请注意,它在编译时非常密集,因此请谨慎使用。

编辑:虽然我确实认为这是一个带有相对简单示例的一般练习,但我确实同意,尽管按照 synek317 的建议,使用伪流类为这个特定示例编码将是一个更灵活和“轻量级”的解决方案。再次实现这样的流不需要你做所有操作符的特化,事实上 boost 再次提供了 IOStreams 库来帮助你将一个类实现为标准的 C++ 流(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
Run Code Online (Sandbox Code Playgroud)