为什么 constexpr 静态成员(类型为类)需要定义?

2024-04-06

==> 查看完整的代码片段和编译coliru http://coliru.stacked-crooked.com/a/e6ebe0ef8a87b601.

我有一个文字类型 http://en.cppreference.com/w/cpp/concept/LiteralType班级填充constexpr要求 http://en.cppreference.com/w/cpp/language/constexpr:

struct MyString
{
    constexpr MyString(char const* p, int s) : ptr(p), sz(s) {}
    constexpr char const* data() const { return ptr; }
    constexpr int         size() const { return sz;  }

    char const *ptr = 0;
    int  const  sz  = 0;
};

我用它作为constexpr static http://en.cppreference.com/w/cpp/language/static#Constant_static_members成员变量:

struct Foo
{
    int size() { return str_.size(); }

    constexpr static MyString str_{"ABC",3};
};

int main()
{
  Foo foo;
  return ! foo.size();
}

But the linker says:
(Clang-3.5 and GCC-4.9)

undefined reference to `Foo::str_'

I have to define the constexpr static member!
(I do not specify the constructor parameters)

constexpr MyString Foo::str_;

然而,如果constexpr static成员曾是int该成员不必在类定义之外定义。这是我的理解,但我不确定......

问题:

  • Why int不需要在类声明之外定义,但是MyString需要这个吗?
  • 定义一个有什么缺点吗?constexpr static头文件中的成员?
    (我仅提供我的库作为头文件)

The 一个定义规则 http://en.wikipedia.org/wiki/One_Definition_Rule告诉我们,我们不能对一个事物有多个定义odr-used http://en.cppreference.com/w/cpp/language/definition程序中的变量。因此,如果变量是 odr 使用的,那么您需要定义它,但不能在头文件中定义它,因为它可能会在整个程序中多次包含。 Odr 使用违规不需要诊断消息,因此您可以违反此规则,编译器没有义务通知您。

在你的情况下,你确实在使用odrstr_,并且您不能在头文件中包含该定义,因为这会违反一次定义规则,因为它可以在程序中包含多次。

有趣的是,如果您执行了以下操作,它就不会被 ODR 使用:

return str_.size_;

因此,您不需要定义变量,在某些示例中这可能会产生一些奇怪的后果 https://stackoverflow.com/q/28506342/1708801。我怀疑这真的能长期解决你的问题。

C++ 标准草案部分涵盖了 ODR 规则3.2他们说:

名称显示为潜在计算表达式的变量 x ex 是 odr 使用的,除非应用左值到右值转换 (4.1) to x 产生一个常量表达式 (5.19),它不调用任何 非平凡函数,如果 x 是一个对象,则 ex 是 表达式 e 的潜在结果集,其中 左值到右值转换 (4.1) 应用于 e,或者 e 是 丢弃值表达式(第 5 条)。如果出现则表示已使用 ODR 作为潜在评估的表达式(包括作为 非静态成员函数体内的隐式转换 (9.3.1)).[...]

So str_产生一个常量表达式,左值到右值的转换不应用于该表达式str_.size()并且它不是一个被丢弃的值表达式,因此它是 odr 使用的,因此str_是需要定义的。

另一方面,左值到右值的转换应用于表达式str_.size_,所以它不是 odr 使用的,也不需要str_被定义为。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 constexpr 静态成员(类型为类)需要定义? 的相关文章

  • 在 C++ 中分割大文件

    我正在尝试编写一个程序 该程序接受一个大文件 任何类型 并将其分成许多较小的 块 我想我已经有了基本的想法 但由于某种原因我无法创建超过 12 kb 的块大小 我知道谷歌等上有一些解决方案 但我更感兴趣的是了解这个限制的根源是什么 然后实际
  • 如果.Net Core可以在Windows上运行,为什么不能在.Net Framework中引用.Net Core DLL?

    我明白为什么 Net Framework 可能会在 Net Core IE 中导致问题 因为不存在特定于 Windows 平台的 API 但是为什么不能直接引用 Net Core 作为 Net Framework 中的库呢 如果 Net C
  • 当我单击 C# 中的“取消”按钮时重定向到新页面(Web 部分)

    Cancel button tc new TableCell btnCancel new Button btnCancel Text Cancel btnCancel Click new EventHandler btnCanel Clic
  • 处理 fanart.tv Web 服务响应 JSON 和 C#

    我正在尝试使用 fanart tv Webservice API 但有几个问题 我正在使用 Json Net Newtonsoft Json 并通过其他 Web 服务将 JSON 响应直接反序列化为 C 对象 这里的问题是元素名称正在更改
  • std::map 和二叉搜索树

    我读过 std map 是使用二叉搜索树数据结构实现的 BST 是一种顺序数据结构 类似于数组中的元素 它将元素存储在 BST 节点中并按其顺序维护元素 例如如果元素小于节点 则将其存储在节点的左侧 如果元素大于节点 则将其存储在节点的右侧
  • TextBox 焦点的 WinForms 事件?

    我想添加一个偶数TextBox当它有焦点时 我知道我可以用一个简单的方法来做到这一点textbox1 Focus并检查布尔值 但我不想那样做 我想这样做 this tGID Focus new System EventHandler thi
  • 获取从属性构造函数内部应用到哪个属性的成员?

    我有一个自定义属性 在自定义属性的构造函数内 我想将属性的属性值设置为属性所应用到的属性的类型 是否有某种方式可以访问该属性所应用到的成员从我的属性类内部 可以从 NET 4 5 using CallerMemberName Somethi
  • 为什么 BOOST_FOREACH 不完全等同于手工编码的?

    From 增强文档 http www boost org doc libs 1 48 0 doc html foreach html foreach introduction what is literal boost foreach li
  • 如何在 VS 中键入时显示方法的完整文档?

    标题非常具有描述性 是否有任何扩展可以让我看到我正在输入的方法的完整文档 我想查看文档 因为我可以在对象浏览器中看到它 其中包含参数的描述和所有内容 而不仅仅是一些 摘要 当然可以选择查看所有覆盖 它可能是智能感知的一部分 或者我不知道它并
  • C++11 函数局部静态 const 对象的线程安全初始化

    这个问题已在 C 98 上下文中提出 并在该上下文中得到回答 但没有明确说明有关 C 11 的内容 const some type create const thingy lock my lock some mutex static con
  • 是否有与 C++11 emplace/emplace_back 函数类似的 C# 函数?

    从 C 11 开始 可以写类似的东西 include
  • 通过不同 DLL 或 EXE 中的指针或引用访问 STL 对象时发生访问冲突

    我在使用旧版 VC6 时遇到以下问题 我只是无法切换到现代编译器 因为我正在处理遗留代码库 http support microsoft com kb 172396 http support microsoft com kb 172396
  • 组合框项目为空但数据源已满

    将列表绑定到组合框后 其 dataSource Count 为 5 但组合框项目计数为 0 怎么会这样 我习惯了 Web 编程 而且这是在 Windows 窗体中进行的 所以不行combo DataBind 方法存在 这里的问题是 我试图以
  • “MyClass”的类型初始值设定项引发异常

    以下是我的Windows服务代码 当我调试代码时 我收到错误 异常 CSMessageUtility CSDetails 的类型初始值设定项引发异常 using System using System Collections Generic
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • 从匿名类型获取值

    我有一个方法如下 public void MyMethod object obj implement 我这样称呼它 MyMethod new myparam waoww 那么我该如何实施MyMethod 获取 myparam 值 Edit
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 我应该在应用程序退出之前运行 Dispose 吗?

    我应该在应用程序退出之前运行 Dispose 吗 例如 我创建了许多对象 其中一些对象具有事件订阅 var myObject new MyClass myObject OnEvent OnEventHandle 例如 在我的工作中 我应该使
  • 以编程方式使用自定义元素创建网格

    我正在尝试以编程方式创建一个网格 并将自定义控件作为子项附加到网格中 作为 2x2 矩阵中的第 0 行第 0 列 为了让事情变得更棘手 我使用了 MVVM 设计模式 下面是一些代码可以帮助大家理解这个想法 应用程序 xaml cs base
  • 热重载时调用方法

    我正在使用 Visual Studio 2022 和 C 制作游戏 我想知道当您热重新加载应用程序 当它正在运行时 时是否可以触发一些代码 我基本上有 2 个名为 UnloadLevel 和 LoadLevel 的方法 我想在热重载时执行它

随机推荐