我正在使用boost_logging(版本2),我想避免在我的代码中乱扔垃圾:
public class CommonElements {
ArrayList<String> commonCollections = new ArrayList<String>();
private int comparisons = 0;
int i, j, k;
int count, lowestCount;
String previousString = "";
int row[];
String current;
public Comparable[] findCommonElements(Comparable[][] collections) {
Arrays.sort(collections[0]);
row = new int[collections[0].length];
for (i = 0; i < collections[0].length; i++) { // first row column selection
current = collections[0][i].toString();
lowestCount = 1;
for (j = 0; j < collections.length; j++) { // row
count = 0;
for (k = 0; k < collections[0].length; k++) { // column
if (current.equals(collections[j][k].toString())) { // if contains same string as first row column selected
count++;
System.out.print(count + "\n");
}
}
if (lowestCount < count) {
lowestCount = count;
}
}
}
System.out.print(lowestCount);
return collections[0];
}
public int getComparisons() {
return comparisons;
}
}
我想到的第二点是,我更喜欢将它们组合在一个像这样的宏中:
BOOST_LOG_NAMED_SCOPE("SomeModuleName")
BOOST_LOG_FUNCTION()
但是当我尝试这样做时,我收到了一个错误。见下文。
对于允许我在模块级别执行#define LOG_NAMED_SCOPE_FUNCTION(name)\
BOOST_LOG_NAMED_SCOPE(name)\
BOOST_LOG_FUNCTION()
之类的操作(也会出错),我会非常满意。更好的是一个解决方案,可以做某种RAII / AOP,让我也可以追加&#34;输入&#34;和&#34;退出&#34;在函数的开头和结尾跟踪消息,因为这是我的最终目标。
我在猜测,因为生成的唯一标识符在宏定义时扩展,而不是在宏调用时扩展。我还看了DEFERRED和EXPAND助手,但我不确定他们是否会在这里帮助我。
以下是错误消息:
BOOST_LOG_NAMED_SCOPE("SomeModuleName")
答案 0 :(得分:1)
您遇到的问题是因为BOOST_LOG_FUNCTION
基本上基于BOOST_LOG_NAMED_SCOPE
- 它添加了一个范围,其名称对应于当前的函数签名。这两个宏都创建一个局部变量,该名称对于源文件的给定行是唯一的(它使用__LINE__
来生成该名称)。根据C / C ++预处理器规则,所有宏都扩展为一行,因此LOG_NAMED_SCOPE_FUNCTION
扩展为同一范围内的两个相同的命名局部变量,因此编译器错误。
解决此问题的一种方法是定义宏,以便它直接为两个范围定义两个不同的变量。变量应该具有named_scope::sentry
类型,这是一个范围保护,在构造和销毁时自动将范围推送并弹出到堆栈。
#define LOG_NAMED_SCOPE_FUNCTION(name)\
boost::log::attributes::named_scope::sentry BOOST_LOG_UNIQUE_IDENTIFIER_NAME(scope_sentry1_)(name, __FILE__, __LINE__);\
boost::log::attributes::named_scope::sentry BOOST_LOG_UNIQUE_IDENTIFIER_NAME(scope_sentry2_)(BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, boost::log::attributes::named_scope_entry::function)
这样每个LOG_NAMED_SCOPE_FUNCTION
都会将两个范围添加到列表中 - 命名范围和当前函数。
但是,根据您的描述,它看起来并不是您想要实现的目标。 Boost.Log不允许直接使用它们所源自的模块的名称来标记日志记录 - 主要是因为没有可移植的方式来了解它,并且非便携方式很昂贵。但有一些方法可以模仿这种行为。以下是一些想法。
最简单的方法是使用您自己的日志记录宏,它将自动添加当前模块名称属性。
// Define the attribute keyword for the module name
BOOST_LOG_ATTRIBUTE_KEYWORD(a_module, "Module", std::string)
#define MY_LOG(lg)\
BOOST_LOG(lg) << boost::log::add_value(a_module, CURRENT_MODULE)
如果将CURRENT_MODULE
定义为在项目设置中命名当前模块的字符串,MY_LOG
宏将自动将其作为属性附加到记录中。请参阅有关attribute keywords和add_value
manipulator的文档。
另一种方法是使用channels。如果不同模块共享记录器,则可以将当前模块名称设置为通道名称。或者,如果您已经使用了频道,请将其作为新的单独属性添加到您创建的每个记录器中。您可以编写自己的logger feature来自动执行该操作。
如果您确实共享记录器,那么您还可以查看scoped attributes的实施方式,尤其是BOOST_LOG_SCOPED_THREAD_TAG
。由于您可能在不同模块之间调用函数,BOOST_LOG_SCOPED_THREAD_TAG
将不适合您(因为如果已经存在,它将不会替换集合中的属性 - 在您的情况下,这意味着您将只看到首先设置属性的模块的名称,但您可以实现类似于适合您的情况的类似的东西。我们的想法是将当前模块名称添加为特定于线程的属性(如果没有添加或替换现有的模块名称)。这必须在范围保护中完成,该范围保护必须在可以从其他模块调用的每个功能中使用。