Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.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++ 不知道派生类型的静态CRTP类?_C++_Templates_Static_Crtp - Fatal编程技术网

C++ 不知道派生类型的静态CRTP类?

C++ 不知道派生类型的静态CRTP类?,c++,templates,static,crtp,C++,Templates,Static,Crtp,给出以下工作代码 #include <iostream> template<class Detail> class AbstractLogger { public: static void log(const char* str) { Detail::log_detailled(str); } }; class Logger : public AbstractLogger<Logger> { public: stat

给出以下工作代码

#include <iostream>

template<class Detail>
class AbstractLogger
{
public:
    static void log(const char* str) {
        Detail::log_detailled(str);
    }
};

class Logger : public AbstractLogger<Logger>
{
public:
    static void log_detailled(const char* str) {
        std::cerr << str << std::endl;
    }
};

int main(void)
{
    AbstractLogger<Logger>::log("main function running!");
    return 0;
}
#包括
模板
类抽象记录器
{
公众:
静态无效日志(常量字符*str){
详细信息:日志详细信息(str);
}
};
类记录器:公共抽象记录器
{
公众:
静态无效日志(const char*str){

如果您的意思是希望有一个库使用它作为日志机制,而不知道确切的实例化类型,那么我建议不要使用它

在满足其他要求(即没有虚拟函数)的情况下,唯一的方法是将库中所有需要记录的函数/类型转换为采用
记录器
类型的模板。最终结果是大部分界面都变成了模板(尽管您可能会将大量实现转移到非模板化代码,但这将使您的生活比需要的困难得多,而且它仍然会生成更大的二进制文件)


如果您对虚拟函数的关注点是性能,那么您应该重新考虑您的方法及其带来的问题。尤其是,日志成本很高。大多数日志库通过优化非日志情况来解决这一问题(通过宏来避免在未启用日志级别/组/…的情况下调用日志),但仍保留动态调度用于实际写入。与写入控制台或文件的成本相比,动态调度的成本可以忽略不计,甚至与生成将被记录的消息的成本相比(我假设您不仅记录文字字符串)

模板类不能“放入库中”,因为它们被编译器实例化为模板参数的专门化


不过,您可以将模板实现中使用的与参数无关的内容放入库中。

通常的方法是针对概念编写代码,同时提供帮助程序,以便用户可以轻松生成满足其中一个或多个概念的类型。例如,
boost::iterator\u facade
之类的东西就是CRTP帮助程序at使用户更容易编写迭代器。然后,该迭代器可以在接受迭代器的任何位置使用——例如在
std::vector
的范围构造函数中。请注意,该特定构造函数对用户定义的类型没有先见之明

在您的情况下,
AbstractLogger
将是CRTP助手。缺少的部分是定义例如记录器概念。因此,请注意,需要记录器的所有内容都需要实现为模板,或者您需要一个类型擦除容器来容纳任意记录器


概念检查(如提供的检查)对于这种编程来说很方便,因为它们允许用实际代码表示概念。

你说我想把
AbstractLogger
放进一个库是什么意思。你是说你想在库中使用它而不知道实例化类型?还是想在库中包含某种生成的代码?还是就像CRT模式的严重设计缺陷和滥用一样…模板在代码中定义时被编译成具体的类表示形式。如果您定义了
AbstractLogger
AbstractLogger
,将编译两个版本。在库中,您必须事先定义可用的内容。谢谢您的回答。可以吗请简要介绍一下这样一个“类型擦除容器”是什么样子?@Johannes它将非常类似于
std::function
,它是一个容器,用于任何可以用签名
R(a…)
调用的内容。因此它将有一个构造函数
模板容器(日志记录器日志)
获取任何符合记录器的内容,并且本身符合记录器概念——将实际操作委托给在构建时传递的记录器。概述了一些类型擦除技术。