我试图定义一个在函数上下文和类主体或名称空间中使用时行为不同的宏。这样做的目的是在引用为BOOST_LOG_NAMED_SCOPE
的LOG_CONTEXT
宏中选择性地包含here(或实现等效行为)。
我尝试了两种方法:
使用BOOST_PP_IF
和预处理器功能来测试是否__func__
是非空的。
基本源文件上的g++ -E
的输出在全局和函数范围内仍然包含文字文本__func__
,因此可能排除了任何针对预处理阶段的方法。
使用类似sizeof(__func__)
的东西来选择实现类似于BOOST_LOG_NAMED_SCOPE
的行为的专用模板。我可以重新使用boost日志中的boost::log::attributes::named_scope::sentry
对象,但是我一直试图找出如何在函数上下文中有条件地实例化它,或者至少以一种在任何地方都可以使用的方式实例化。以下构造在类定义和函数中似乎可以正常工作,但是在将多个转换单元链接在一起时,失败,并出现“多重定义”错误,这些转换单元包括在全局或命名空间范围内包含带有LOG_CONTEXT
的标头:
#include <boost/log/attributes/named_scope.hpp>
#include <type_traits>
namespace logging {
namespace attrs = boost::log::attributes;
namespace detail {
// Default no-op on construction when not in a function.
template<typename ScopeTraits, bool InFunction>
class named_scope_helper
{};
// Specialization when in a function.
template<typename ScopeTraits>
class named_scope_helper<ScopeTraits, true> :
public attrs::named_scope::sentry
{
public:
named_scope_helper() BOOST_NOEXCEPT
: sentry(
ScopeTraits::scope_name(),
ScopeTraits::filename(),
ScopeTraits::lineno() )
{}
};
template<size_t N>
class not_1 : public std::true_type
{};
template<>
class not_1<1> : public std::false_type
{};
#define LOGGING_LOG_IN_FUNCTION \
::logging::detail::not_1<sizeof(__func__)>::value
} // namespace detail
} // namespace logging
// scope_name_t/filename_t are required since attrs::named_scope::sentry
// requires string literals.
#define LOG_CONTEXT( name_ ) \
struct __logging_log_scope_traits__ \
{ \
using scope_name_t = const char (&)[sizeof(name_)]; \
static scope_name_t scope_name() \
{ return name_; } \
using filename_t = const char (&)[sizeof(__FILE__)]; \
static filename_t filename() \
{ return __FILE__; } \
static size_t lineno() \
{ return __LINE__; } \
}; \
::logging::detail::named_scope_helper< \
__logging_log_scope_traits__, LOGGING_LOG_IN_FUNCTION> \
BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_log_named_scope_sentry_);
我通常的解决方法是在static
的声明中使用_log_named_scope_sentry_
,但这违反了目的。
我可以添加另一个严格用于非执行上下文的宏,但是要首先研究这种方法,因为这将是一个有趣的技巧。我如何继续上面已开始的两种方法之一,或者还有我没有考虑过的另一种选择?
首选通用解决方案,但我只真正关心GCC和Clang。