- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
考虑以下代码:
#include <iostream>
#include <cstdlib>
#include <ctime>
struct BaseClass {
static int identifier() {
static int identifier_counter = 0;
return identifier_counter++;
}
};
template <class D>
struct Class: public BaseClass {
static int identifier() {
static int class_identifier = BaseClass::identifier();
return class_identifier;
}
};
struct A: public Class<A> { };
struct B: public Class<B> { };
int main() {
std::srand(std::time(0));
int r = std::rand()%2;
if(r) {
std::cout << "A: " << A::identifier() << std::endl;
std::cout << "B: " << B::identifier() << std::endl;
} else {
std::cout << "B: " << B::identifier() << std::endl;
std::cout << "A: " << A::identifier() << std::endl;
}
}
这是对问题的简化但仍然合理的表示。
任何派生类在运行时都会有一个特定的、不同的标识符,并且相同类型的两个实例将共享相同的标识符。对于这样的问题当然是一个很好的解决方案。
不幸的是,这些标识符取决于调用 identifier
成员的顺序(我们可以通过多次运行示例轻松地看到它)。换句话说,给定两个类 A
和 B
,如果碰巧运行两次软件,它们的 identifier
成员以不同的顺序被调用,它们有不同的标识符。
我的问题是,出于某些原因,我需要将这些标识符存储在某处,并让它们在单次执行后继续存在,这样我就可以在应用程序再次运行时根据原始类型进行推理,并决定从存储。
另一种方法是使用 hash_code来自 type_info
,但它还有其他问题。另一种解决方案是在应用程序的 Bootstrap 期间强制调用 identifier
成员,但是这个也有几个缺点。
我想知道到目前为止是否有一种易于实现但仍然优雅的解决方案,它对开发人员完全透明,可以在多次执行中识别类型,因为上面的解决方案是针对应用程序的单次运行。
最佳答案
C++ 无法解决每个类都具有唯一持久标识符的问题。对不起。您将依赖于调用初始化函数的顺序,或者,如果您从静态对象的初始化器中调用它们,则取决于静态初始化器的顺序(这通常取决于链接行中目标文件的顺序)。
当然,不能保证哈希值是唯一的。
为此您必须使用外部脚本。特别是,可能会使用这样的东西:
// when class is first created
class Foo {
static int class_id = ?CLASS_ID?;
};
// after class is process by the script
class Foo {
static int class_id = 123; // Autogenerated by 'stamp_id.pl'
};
你可能有一个 perl 脚本作为编译的一部分运行(第一件事),它打开项目目录中的所有 .h 文件,读取所有这些文件,计算 Autogenerated by 'stamp_id.pl 的所有实例'
然后用递增的计数器标记所有 ?CLASS_ID?
(从已经生成的 ID 的数量开始)。为了增加一些安全性,您可能需要一个比简单的 ?...? 更好的模式,但我认为,您明白了。
关于c++ - CRTP 和唯一持久标识符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34008110/
我目前正在实现一个通用事件类。事件处理程序有一个发送者参数和可变数量的事件参数。所以事件类的声明如下: template class event; 为了允许某些实现细节,我需要事件的 CRTP,如下所
我需要实现对实现相同接口(interface)的对象 vector 的高效访问。直到现在,我一直在使用带有虚函数的继承:接口(interface)被定义为具有纯虚函数的抽象类,每个对象类都实现了虚函数
在CRTP ,基类可以使用派生类的函数和变量。但是,派生类的类型不能直接被基类使用,见下面代码: #include template class A { public: //using S
我创建了一个模板类,只要发生实例化,它就会触发运行时文本输出: template struct verbose { verbose() { std::cout str
假设我有一个用于矩阵的 CRTP 模板类 template class MatrixBase{ private: //... public: Derived some_function
我已经阅读了很多关于 Curiously Recurring Template Pattern 的帖子而且我仍然不明白为什么我不想只使用模板编程来使用它。 下面是一个从维基百科稍作修改的例子: tem
请帮我解决以下问题: 我有一个类声明为: template class Rim : /* Derive from GenericComponent Design perspective u
有没有办法从 CRTP 基类查询派生类的内容,与 SFINAE 一起使用来启用或禁用基类方法? 我想要完成的可能如下所示: template struct base { struct foo
我有兴趣了解 CRTP。我想为引擎实现一个组件系统,我不想访问组件统一风格 GetComponent("withThisName"); 而是在编译时(虚幻风格) GetComponent(); 虽然实
让我们考虑一个用于打印派生类的 CRTP 模板类 Print: template struct Print { auto print() const -> void; auto se
最近我一直在摆弄模板并偶然发现了以下问题。我正在像这样实现 CRTP 模式: template struct protocol_object { ... }; struct data_obje
我正在尝试在固定大小的缓冲区中构建一条消息,我的图书馆的用户会在其中提供一些数据。我曾经通过给用户一个指向缓冲区的指针并让他们写入它,并通过引用他们写入的字节数来设置一个 size_t 参数来做到这一
我刚刚遇到 CRTP 的问题,我不能在基类和派生类中使用相同的方法名称(具有不同的签名)。重现此问题的示例如下: template struct Base { void foo(){}
考虑以下代码: #include #include #include struct BaseClass { static int identifier() { stati
我有一个纯虚类接口(interface): class Interface { public: virtual ~Interface() noexcept; virtual voi
任何人都可以向我解释为什么 base::blah(string str) 的签名必须是一个字符串而不是引用一个字符串。如果它是一个字符串,编译器会出现以下错误。是因为在模板实例化时编译器拒绝任何隐式转
我遇到了以下代码(存储在 crtp.cc 中)的编译器相关问题: #include #include #include template class AlgebraicVectorExpres
在我的一个项目中,我使用与此处的答案 1 相同的 CRTP 方法(源自 enable_crtp):How do I pass template parameters to a CRTP? 但是我也需要
我目前正在使用 C++ 模板处理 CRTP 模式。在摆弄 visual studio 时,我发现了几种派生类可以调用函数的基类实现的方式/方法。下面是我正在使用的代码以及 3 行注释掉的代码,显示了如
我想创建一个模板类,为类提供通用方法,使其具有成员 m_Type,指定继承类提供的某种类型。考虑一下: template struct TypeAttribute { T m_Type; };
我是一名优秀的程序员,十分优秀!