c++ - 如何根据构造函数参数为类成员函数模板化代码

标签 c++ templates c++17

我有一个对性能高度敏感(读取低延迟要求)的 C++ 17 日志记录类,它的成员函数可以在本地记录或远程记录,具体取决于实现该类的标志。 “远程日志记录”或“本地日志记录”功能在构造对象时已完全定义。

代码看起来像这样

class Logger {
public:
    Logger(bool aIsTx):isTx_(aIsTx) {init();}
    ~Logger() {}

    uint16_t fbLog(const fileId_t aId, const void *aData, const uint16_t aSz){
        if (isTx_) 
                      // do remote logging
                      return remoteLog(aId, aData, aSz);
        else 
                      // do local logging
                      return fwrite(aData, aSz, 1,fd_[aId]);
    }
protected:
bool isTx_
}

我想做的是

  • 一些删除 if(isTx_) 的方法,以便在实例化时定义要使用的代码。
  • 由于类对象被多个其他模块使用,我不想将类模板化,因为这将需要我将类的两个模板化实现包装在接口(interface)包装器中,这将导致每次调用 v-table成员函数被调用。

最佳答案

您不能“模板化”行为,因为您希望选择在运行时完成。

如果您因为性能问题想要去掉 if,请放心,与磁盘访问或网络通信相比,它的影响可以忽略不计。虚函数调用也是如此。

如果您需要低延迟,我建议考虑异步日志记录:主线程只需将消息复制到内部缓冲区。内存比磁盘或网络快得多,因此延迟会少得多。然后,您可以有一个单独的服务线程等待缓冲区接收消息,并处理缓慢的通信。

作为奖励,您不需要在主线程中使用分支或虚函数,因为它是决定如何处理消息的服务线程。

然而,异步并不是一种简单的方法。有许多情况必须考虑:

  • 如何同步对缓冲区的访问(我建议尝试使用无锁队列)。
  • 应该允许缓冲区占用多少内存?没有限制,如果程序记录速度快于写入速度,它可能会消耗太多。
  • 如果达到缓冲区限制,主线程应该做什么?它要么需要在处理缓冲区时回退到同步等待,要么需要丢弃消息。
  • 程序崩溃时如何刷新缓冲区?如果不可能,那么最后的消息可能会丢失 - 这可能是您首先需要弄清楚程序崩溃的原因。

无论选择如何:如果性能至关重要,则尝试多种方法并进行衡量。

关于c++ - 如何根据构造函数参数为类成员函数模板化代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57983794/

相关文章:

c++ - 使用枚举器的漂亮方法

c++ - 派生类是否间接继承基类的赋值运算符?

visual-studio - Visual Studio 项目模板多个项目类型

c++ - 在编译器生成的复制构造函数上强制模板化构造函数

c++ - 如何在 C++ 中将 chrono::seconds 转换为 HH:MM:SS 格式的字符串?

c++ - QT背景图片

c++ - 如何在 SOAP 消息中发送密码

css - 提醒系统模板

c++ - 根据转换后的值查找最小元素

c++ - 将从不可复制派生的对象放置到 vector 中