【发布时间】:2018-12-22 06:59:08
【问题描述】:
在a project of mine 中,我有一个ID generator 用于看起来与此类似的类型:
class Family {
static std::size_t identifier;
template<typename...>
static std::size_t family() {
static const std::size_t value = identifier++;
return value;
}
public:
template<typename... Type>
inline static std::size_t type() {
return family<std::decay_t<Type>...>();
}
};
std::size_t Family::identifier{};
用法:
const auto id = Family::type<FooBar>();
对于我的目的来说它工作得很好,但它有一些限制。最烦人的一个(问题的目的)是,如果所有链接到共享库的可执行文件都尝试创建标识符,它就会失败。结果通常是因为每个共享库都维护自己独立的Family::identifier,所以第n 个标识符被跨边界分配给不同的类型。
一些共享库人员指出,如果有一个更可靠的解决方案,我们将不胜感激,但没有提出一个不会破坏性能的解决方案(几乎所有这些人都引入了容器、查找功能和内存分配)。
是否有任何替代方法可以解决上述限制而不损失当前设计的性能?
我搜索了 SO 并找到了一些有趣的答案。其中许多已经有好几年了。只要现有类的接口保持不变,我想探索最新版本的标准的解决方案。
This one 是最有趣的一个。它使用静态成员的地址来实现相同的目的,但它不符合顺序生成标识符的想法
注意:很遗憾,不能使用 RTTI。
注意 : ids 必须按顺序生成,从 0 开始,如上述解决方案。
【问题讨论】:
-
那是很多 C++ 版本标签。最好专注于您实际使用的版本,因为所有以前的版本都是隐含的。
-
@tadman 实际上,一个至少适用于其中一个标签的解决方案对我来说很好。这就是为什么我把它们都放进去。如果您发现它们不是必需的,请随时编辑列表。我不确定还有哪些其他标签适合此类问题。感谢您的帮助。
-
@Justin 好点。不,RTTI 不是一个选项。我正在编辑问题以添加此注释。谢谢。
-
我会使用静态类成员的地址作为唯一的类型标识符。只要 ODR 统治一天,一个空的
class Identifier{};,我所有的类中都有一个静态类成员Identifier id;,并且类成员的地址作为我的标识符。为了迂腐正确,我总是使用std::less<Identifier *>;来比较我的伪 ID,因为在 C++11 之后,std::less保证实现不相关指针的严格弱排序。 -
比这更小心地使用标签。如果你能做 C++17,那就太好了,C++14 和 C++11 标签是多余的。当人们寻找要回答的问题时,他们不太可能寻找 C++11 特定的问题,他们会寻找 C++。使用其他标签来尝试对您的问题进行分类。例如,Boost 是一种选择吗?
标签: c++ shared-libraries c++17