Boost.Log宏扩展和条件三元运算符

时间:2013-12-31 17:44:10

标签: c++ boost macros c-preprocessor

我正在尝试编译:

#include <boost/log/trivial.hpp>

int main(int argc, char* argv[]) {
  BOOST_LOG_TRIVIAL(info) << "test Boost.Log";
  true ? 0 : BOOST_LOG_TRIVIAL(info) << "this fails";
}

编译命令:

clang++ main.cc -o main \
  -lboost_log -lboost_log_setup -lboost_thread -lboost_system -pthread --static

上面抛出错误:

main2.cc:5:18: error: expected expression
      true ? 0 : BOOST_LOG_TRIVIAL(info) << "this fails";
                 ^
/usr/local/include/boost/log/trivial.hpp:113:5: note: expanded from macro 'BOOST_LOG_TRIVIAL'
    BOOST_LOG_STREAM_WITH_PARAMS(::boost::log::trivial::logger::get(),\
    ^
/usr/local/include/boost/log/sources/record_ostream.hpp:317:5: note: expanded from macro 'BOOST_LOG_STREAM_WITH_PARAMS'
    BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_), params_seq)
    ^
/usr/local/include/boost/log/sources/record_ostream.hpp:306:5: note: expanded from macro 'BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL'
    for (::boost::log::record rec_var = (logger).open_record((BOOST_PP_SEQ_ENUM(params_seq))); !!rec_var;)\
    ^
1 error generated.

以上是我在尝试创建宏时遇到的问题:

#define LOG_IF(lvl, condition) \
  !(condition) ? 0 : BOOST_LOG_TRIVIAL(lvl)

运行g ++以扩展宏(g++ -E -C -P -o pre.cc main.cc):

int main(int argc, char* argv[]) {
  for (::boost::log::record _boost_log_record_4 = (::boost::log::trivial::logger::get()).open_record((::boost::log::keywords::severity = ::boost::log::trivial::info)); !!_boost_log_record_4;) ::boost::log::aux::make_record_pump((::boost::log::trivial::logger::get()), _boost_log_record_4).stream() << "test Boost.Log";
  true ? 0 : for (::boost::log::record _boost_log_record_5 = (::boost::log::trivial::logger::get()).open_record((::boost::log::keywords::severity = ::boost::log::trivial::info)); !!_boost_log_record_5;) ::boost::log::aux::make_record_pump((::boost::log::trivial::logger::get()), _boost_log_record_5).stream() << "this fails";
}

它失败的原因很明显(表单编译错误)。但在这一点上,我不知道如何解决它。

2 个答案:

答案 0 :(得分:0)

正如@KennyTM建议:

#define LOG_IF(lvl, condition) \
  if (condition) BOOST_LOG_TRIVIAL(lvl)

效果很好(谢谢!)。

但是我仍然对条件表达式是否可以与Boost记录宏一起使用感兴趣。

答案 1 :(得分:0)

答案就在您粘贴的错误消息中。经过几个中间步骤后,BOOST_LOG_TRIVIAL扩展为for 语句。三元运算符形成表达式,并且语句不能构成基本C系列语法中表达式的直接部分,因此失败。 for对于语句的操作是不可或缺的(它提供了一种方法,可以在左侧的部分之后执行某些操作,或者通过在前面插入额外的语句或者通过创建一个范围块),所以只需重写宏不容易完成。

如果你想要一个快速而又狡猾的建议,你可以使用GCC语句表达式,或者可能使用lambdas(噪音很大但标准):

true ? ({0;}) : ({ BOOST_LOG_TRIVIAL(info) << "this fails"; });

如果你想要更多......某种东西......看起来与原版大致相似的解决方案,你可以尝试将它包装在一个包含的对象中:

#define LOG_TRIVIAL_EXPR(inf) TrivLogger([](std::string msg){ BOOST_LOG_TRIVIAL(inf) << msg; })

template<typename M>
class TrivLogger {
    typedef std::function<void(std::string)> F;
    F thunk;
    TrivLogger(F th) : thunk(th) {}
    TrivLogger<M> operator<<(std::string msg) {
        thunk(msg); return this;
    }
}

//...
true ? 0 : LOG_TRIVIAL_EXPR(info) << "this should work";

(说实话我不知道我是否做得对......)