我有一个运行时布尔值
verbose
,如果false
排除一些打印到标准输出。
要确定想法,请考虑有很多部分,例如:
void add(const int a, const int b, const bool verbose)
{
//...
if(verbose) std::print("{}+{}={}\n", a, b, a+b);
}
我的目标是拥有类似的东西:
template<typename F>
void add(const int a, const int b, F print_if_verbose)
{
//...
print_if_verbose("{}+{}={}\n", a, b, a+b);
}
这样做的动机是简化代码并使其不易出错(忘记测试每次打印
verbose
),同时也是为了避免各个子系统了解verbose
参数。
我的第一次尝试是(godbolt):
template<typename F>
void add(const int a, const int b, F print_if_verbose)
{
print_if_verbose("{}+{}={}\n", a, b, a+b);
}
int main(const int, const char* const argv[])
{
const bool verbose = get_verbose_arg(); // runtime boolean
// This doesn't compile, types are different
//const auto vprint = verbose ? [](const std::string_view msg, const auto&... args){std::vprint_unicode(msg, std::make_format_args(args...));}
// : [](const std::string_view, const auto&...){};
//add(1, 2, vprint);
// This works, but ugly
const auto verb_print = [](const std::string_view msg, const auto&... args){ std::vprint_unicode(msg, std::make_format_args(args...)); };
const auto no_print = [](const std::string_view, const auto&...){};
if(verbose) add(2, 3, verb_print);
else add(2, 3, no_print);
// This works, but tests 'verb' each call
const auto maybe_print = [verb=verbose](const std::string_view msg, const auto&... args){ if(verb) std::vprint_unicode(msg, std::make_format_args(args...)); };
add(3, 4, maybe_print);
}
有没有一种方法可以让我在不每次都测试
verbose
的情况下获得一次分配函子的方法?
不确定我是否理解这个问题,但也许您正在寻找这个(为了简洁起见,省略了所有格式详细信息):
#include <iostream>
#include <string>
template <typename F>
void foo(F f) {
f("hello");
}
int main() {
const bool verbose = false;
auto logger = verbose ? +[](const std::string& s){std::cout << s;} : [](const std::string& s) {};
foo(logger);
}
是否打印某些内容的决定仅检查一次。
并非所有 lambda 都可以转换为函数指针,在最坏的情况下,您需要求助于具有 2 个实现的手写函子。您将无法避免分支或间接级别。无论是作为虚拟函数调用还是作为条件检查
bool
,对于运行时值,必须在某处做出一些决定。