Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否可以在C+;中实现一次日志+;20没有宏?_C++_C++20 - Fatal编程技术网

C++ 是否可以在C+;中实现一次日志+;20没有宏?

C++ 是否可以在C+;中实现一次日志+;20没有宏?,c++,c++20,C++,C++20,我正在寻找的是日志功能,它将记录消息,但每个调用站点只记录一次 记录第一次发生的错误、超时等,而不滥发cout/log文件,这将非常有用 传统上,它是用宏实现的(在这里,它们扩展到一些静态bool/计数器,您可以先查看LOG\u\N以了解详细信息),但我想知道在C++20中,它是否可以不用宏实现 我所尝试的: 基于此,由于std::source\u location::current()的魔力无法正常工作,因此无法正常工作 注意:我知道我可以有一个静态std::set/std::unordere

我正在寻找的是日志功能,它将记录消息,但每个调用站点只记录一次

记录第一次发生的错误、超时等,而不滥发cout/log文件,这将非常有用

传统上,它是用宏实现的(在这里,它们扩展到一些静态bool/计数器,您可以先查看LOG\u\N以了解详细信息),但我想知道在C++20中,它是否可以不用宏实现

我所尝试的: 基于此,由于
std::source\u location::current()
的魔力无法正常工作,因此无法正常工作


注意:我知道我可以有一个静态std::set/std::unordered_调用站点集,但我对与邪恶宏解决方案一样高效的解决方案感兴趣。

由于每个lambda表达式的类型不同,您可以使用lambda表达式标记对同一函数的调用

例如:

#include <iostream>


template <typename T,typename F>
void once(T t, F f){
    static bool first = true;
    if (first) {
        f();
        first = false;
    }
} 

int main(){
    for (int i=0; i <1000; ++i){
        once([](){},[](){ std::cout << "A";});
    }
    for (int i=0; i <1000; ++i){
        once([](){},[](){ std::cout << "B";});
    }

}

但是,
once([](){},
有点笨拙,使用宏仍然很诱人。

您可以将逻辑包装在模板中,在C++20中,lambda可以用作默认模板参数:

if(error)
  static const bool error_logged=error_log << "message\n";
所以你可以这么做

模板
//或模板
void simple_do_一次(F/*,Tag={}*/)
{
静态标准::once_标志;
std::调用_一次(标志,f);
}

如果(static bool first=true;first){…},你甚至可以做
。还有其他方法。挑剔:我想你可以跳过[]{}中的()C++20允许lamba作为默认模板参数,以避免调用站点上的样板文件。除了每次调用都是相同的lambda之外,不是吗?我会很惊讶它在每个调用站点上都会生成一个新类型。不可否认,这并不令人震惊,但令人惊讶。我也会担心标准会改变主意,如果它不是真的、真的明确的话;它会使我感到惊讶在每个调用站点上使用一个不同的类型看起来很昂贵。@Yakk AdamNevraumont:从演示中可以看出,它确实可以在一个编译器的一个版本中工作,但是标准要求它吗?不能将
typename Tag=decltype([](){})
替换为
auto Tag=[]{}
?对于每个调用,它仍然是不同的类型(据我所知),那么这也应该有效,不是吗?@Fureeish:两者都有效,甚至更喜欢
auto=[]{}
,version。但是如果您想自己指定标记,使用
typename
版本似乎更方便。
if(error)
  static const bool error_logged=error_log << "message\n";
return a?b:(log("error!"), c);