gpt4 book ai didi

c++ - 多态记录器(虚拟模板函数?)

转载 作者:太空狗 更新时间:2023-10-29 21:33:39 26 4
gpt4 key购买 nike

语境

我有几个软件使用的库。有些是基本的命令行,有些有 Qt UI。

我想在这个库中实现一个独特的日志类,这样每个软件都可以使用它。但是,如果我们在 Qt 环境中,我想使用 qDebug()具有特定功能的 QtMessageHandler .目标是能够在这个库中记录错误,日志将以不同的方式打印,这取决于该库是否在 UI 环境中使用(该库不依赖于 Qt)。


我想要什么

在全局范围内,我想要这样的东西:

class Logger
{
public:
template <class T>
void log(const T& tolog) { handler.log(tolog); }

void setHandler(HANDLER???& h) { handler = h; }
const HANDLER???& getHandler() const { return handler; }

private:
HANDLER??? handler;
}

处理程序对于命令行软件来说非常简单,例如:

class CLHandler
{
public:
template <class T>
void log(const T& tolog) { out << tolog << std::endl; }

private:
std::ostream out;
}

对于 UI,我想使用 qDebug()所以我可以设置自定义 QtMessageHandler在 UI 中打印错误,并将其记录在文件中:

class UIHandler
{
public:
template <class T>
void log(const T& tolog) { qDebug() << tolog; }
}

问题

如您所见,问题出在Logger类中: 处理程序将是什么类型?

由于虚拟模板函数,我无法真正创建接口(interface):

class IHandler
{
public:
virtual ~IHandler() = default;

template <class T>
virtual void log(const T& tolog) = 0; // ERROR templated virtual function!
}

需要帮助

我想要 IHandler::tolog要模板化的函数,因为我想使用 operator<< 的强大功能对于ostreamqDebug() .而且我不想自己重新实现所有重载(ostream 的长列表,qDebug 的列表更长!)。

我想实现它,无论如何(lambda 功能与 auto ?)...欢迎任何建议(我可能在这里做错了什么?)。

谢谢:)

最佳答案

显然不可能拥有模板化虚函数,但您可以使用类型删除来“删除”具体类型,因此您不再需要模板。

基本上,您创建一个接口(interface) ILoggableValue,它知道如何使用 QDebugstd::ostream 流记录您的值,并使用为不同类型生成具体实现的模板:

class ILoggableValue {
public:
virtual ~ILoggableValue() = default;
virtual void log(QDebug &os) const = 0;
virtual void log(std::ostream &os) const = 0;
};

template <typename T>
class LoggableValue : public ILoggableValue {
public:
LoggableValue(const T &value) : value{value} {}
void log(QDebug &os) const override {
// implementation of log for QDebug goes here
os << value;
}
void log (std::ostream &os) const override {
// implementation of log for std::ostream goes here
os << value << std::endl;
}
private:
const T &value;
};

然后,您按照建议的方式创建 IHandler,但现在您可以使用 ILoggableValue 删除模板:

class IHandler {
public:
virtual ~IHandler() = default;
virtual void log(const ILoggableValue &tolog) const = 0;
};

class CLHandler : public IHandler {
public:
explicit CLHandler(std::ostream &out) : out{out} {}
void log(const ILoggableValue &tolog) const override {
tolog.log(out);
}
private:
std::ostream &out;
};

class UIHandler : public IHandler {
public:
void log(const ILoggableValue &tolog) const override {
tolog.log(qDebug());
}
};

最后,您在 Logger 中使用 IHandler:

class Logger {
public:
Logger(std::unique_ptr<IHandler> h) : handler(std::move(h)) {}
template <class T>
void log(const T& tolog) { handler->log(LoggableValue<T>(tolog)); }

void setHandler(std::unique_ptr<IHandler> &h) { handler = std::move(h); }
const IHandler &getHandler() const { return *handler; }

private:
std::unique_ptr<IHandler> handler;
};

Here是一个活生生的例子。

关于c++ - 多态记录器(虚拟模板函数?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50563940/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com