【问题标题】:constexpr pointer to constexpr static member in C++17constexpr 指向 C++17 中的 constexpr 静态成员的指针
【发布时间】:2019-12-26 18:20:16
【问题描述】:

在以下代码中,我将地址分配给静态 constexpr 成员:

struct component_type_data{};

template<class Derived>
class component{
    private:
    const constexpr static component_type_data type_data{};
    public:
    static constexpr const component_type_data* component_type = &type_data;
};

我的动机是为类型设置编译时唯一 ID。

这有效吗?代码仅从 C++17 开始编译。我可以将该指针用作模板参数。

如果这有效,编译器如何事先知道地址?

更新:

另外,跨 dll 边界会发生什么?对于同一个静态成员,每个 dll 都有自己唯一的地址,或者它们会相同?

【问题讨论】:

  • @francesco 部分,我仍然不明白编译器如何事先知道成员地址。跨 dll 边界会发生什么?对于同一类型/成员,每个 dll 都有自己的唯一地址?
  • @francesco 这可能会解决 OP 的动机,但不能回答提出的实际问题。
  • 这能回答你的问题吗? Compile-time constant id

标签: c++ c++17


【解决方案1】:

这有效吗?

是的;一个constexpr指针对象允许包含任何静态存储对象的地址。

代码仅从 C++17 开始编译。

在 C++17 之前,static constexpr 数据成员也需要类外定义:

template <class Derived>
constexpr const component_type_data component<Derived>::type_data;

template <class Derived>
constexpr const component_type_data* component<Derived>::component_type;

如果这有效,编译器如何事先知道地址?

如果您指的是数字地址:答案是编译器通常无法知道这一点,因为它可能直到链接时间或什至可能直到操作系统加载程序时才被分配。

但是,地址可以用作常量表达式的原因是编译器有效地用符号表示它们,component&lt;int&gt;::type_data的地址”。如果你在编译时取消引用这样的指针,编译器会知道结果是“左值引用component&lt;int&gt;::type_data”。因此,C++ 中的编译时计算非常复杂,并且涉及大量元数据(在 C++17 后的世界中,我们对编译器的期望很高)。请注意,一旦您尝试检查数字地址(使用reinterpret_cast),您将不再拥有在编译时可用的东西。

【讨论】:

  • 很好,我忘了问 - 跨 dll 边界会发生什么?对于同一个静态成员,每个 dll 都会有自己唯一的地址,还是一样?
  • 您可以编辑以添加有关编译单元边界和链接器的注释吗?我的预感是component&lt;int&gt;::component_type 在链接在一起时两个.o 文件之间不会 相同,但我不知道如何确定。谢谢!
  • @robs 你是什么意思?它(隐式)是一个内联变量。并且编译单元之间的内联变量是相同的。 Dll 不在标准范围内,因此将取决于平台。
  • Re: 相同,我的意思是如果 libfoo 和 libbar 每个都有 component&lt;int&gt; 并且每个都有一个函数来公开它的 component_type 并且你(静态地)将一个程序与这两者链接起来,这些函数会返回运行时相同的值?
  • @RobStarling 静态库 = 相同;动态库 = 定义的实现。
猜你喜欢
  • 1970-01-01
  • 2021-09-10
  • 2018-10-09
  • 1970-01-01
  • 2019-10-06
  • 2018-01-02
  • 2012-05-09
相关资源
最近更新 更多