我在图表上有许多用于社区检测的算法,我现在想要将它们可视化。这种可视化要求我在执行和记录他们正在做的事情时“劫持”这些算法。具体而言,这将意味着将对std::vector<graph_partition>
的引用作为这些算法的参数传递,并在算法进行时附加到该向量。
因此,对于每个算法(通常只是函数),我需要为&std::vector<graph_partition>
添加另一个参数,并为记录添加一行或两行代码。
我并不总是希望/需要记录,因此以智能的方式这样做已经证明是非平凡的。我想到了:
&std::vector<graph_partition>
传递什么?此外(可能是微不足道的)持续评估条件的运行时命中。任何有关这些的想法或想法都将受到赞赏。
答案 0 :(得分:2)
如果你喜欢使用模板,我认为你真的不需要 variadic 模板。如果您很乐意重新编译以打开和关闭日志记录:
struct NoLogging {
void log(const graph_partition &) {}
};
struct Logging {
std::vector<graph_partition> vec;
void log(const graph_partition &p) {
vec.push_back(p);
}
};
template <typename Logger>
void some_algorithm(Logger &logger) {
// do some stuff
logger.log(something);
}
// optionally, for convenience
void some_algorithm() {
NoLogging l;
some_algorithm(l);
}
// user writes:
some_algorithm();
// or
Logging l;
some_algorithm(l);
// do something with l.vec
这与“默认只记录,即使我不需要它”之间的区别在于,即使是模糊的编译器也会完全删除log
中对some_algorithm<NoLogging>
的调用,因为它可以看出他们什么都不做。
如果您不想重新编译,可以在两个不同的实例集之间进行运行时切换 - 通过提供所有算法的一些多态接口可能会或可能不方便这样做,并且有两个衍生类,来自这样的模板:
template <typename Logger>
struct ConcreteAlgorithms : public Algorithms {
Logger logger;
static void some_algorithm() {
::some_algorithm(logger);
}
// more algorithms
};
Algorithms *get_algorithms(bool with_logging) {
if (with_logging) {
return new ConcreteAlgorithms<Logging>;
} else {
return new ConcreteAlgorithms<NoLogging>;
}
}
但是,此时你将会遇到两个不同版本算法的代码膨胀,所以你可能更喜欢使用logger多态并采用(可能很小的)运行时开销,而不是Mark的答案。
答案 1 :(得分:1)
将指向父日志记录类的指针传递给每个函数。让一个日志类的子实现日志记录功能作为无操作,并在您不需要日志记录时使用该日志。真正的日志记录类也是一个子类,它将包含向量或对它的引用。