为什么我在此处收到“子项具有其类型使用匿名命名空间的基数”警告

2024-01-20

我试图理解为什么在尝试编译此代码时收到警告 -Wsubobject-linkage:

base.hh

#pragma once

#include <iostream>

template<char const *s>
class Base
{
public:
  void print()
  {
    std::cout << s << std::endl;
  }
};

child.hh

#pragma once

#include "base.hh"

constexpr char const hello[] = "Hello world!";

class Child : public Base<hello>
{
};

main.cc

#include "child.hh"

int main(void)
{
  Child c;
  c.print();
  return 0;
}

跑步时g++ main.cc我收到这个警告:

In file included from main.cc:1:
child.hh:7:7: warning: ‘Child’ has a base ‘Base<(& hello)>’ whose type uses the anonymous namespace [-Wsubobject-linkage]
    7 | class Child : public Base<hello>
      |       ^~~~~

如果模板化值是 int 或将 child.hh 复制到 main.cc 中,则不会出现此警告 我不明白这个警告的合理性,以及我应该从中理解什么。


这个警告是适当的,只是措辞有点不清楚。

hello被宣布constexpr,以及冗余的const. A const变量通常具有内部链接(有一些例外,例如变量模板,inline变量等)。

所以hello在模板参数中Base<hello>是一个指向内部链接对象的指针。在每个翻译单元中,它将引用不同的hello该翻译单元本地。

最后Base<hello>在不同的翻译单元中将是不同的类型,所以如果你包括child.hh在多个翻译单元中,您将违反 ODRChild的定义,因此您的程序将具有未定义的行为。

警告正在告诉你这一点。指某东西的用途 ”匿名命名空间“不好。应该这样说”其类型指的是具有内部链接的实体”。但除此之外,它恰恰说明了问题。

仅当您使用对象的指针或引用作为模板参数时,才会发生这种情况。如果您只获取变量的值,那么该变量是否具有内部或外部链接并不重要,因为类型Base<...>将由变量的值决定,而不是变量的身份。


我不知道为什么你需要模板参数作为这里的指针,但如果你真的需要它并且你实际上想要包含.hh多个文件.cc文件(直接或间接),那么你需要给出hello外部链接。那么你就会遇到一个问题,外部链接变量只能在一个翻译单元中定义,你可以通过使变量inline:

inline constexpr char hello[] = "Hello world!";

inline意味着外部链接(即使变量是const) and constexpr暗示const.


如果您只需要字符串的值,而不需要变量的标识,那么从 C++20 开始,您可以传递std::array<char, N>作为模板参数:

#include<array>
#include<concepts>

/*...*/

template<std::array s>
requires std::same_as<typename decltype(s)::value_type, char>
class Base
{
public:
  void print()
  {
    std::cout << s.data() << std::endl;
  }
};

/*...*/

constexpr auto hello = std::to_array("Hello world!");

有了这种联系就变得无关紧要了。写作Base<std::to_array("Hello world!")>也是可以的。

在 C++20 之前,确实没有任何好的方法来按值传递字符串作为模板参数。

即使在 C++20 中,您也可能需要考虑编写自己的std::array-类似专门用于握持字符串的类。这样的类需要满足以下要求结构类型 https://en.cppreference.com/w/cpp/language/template_parameters. (std::string不满足它们。)另一方面,您可能希望通过使用来扩大允许的模板参数类型std::range概念和std::range_iter_t代替std::array允许可以表示字符串的任何类型的范围。如果您不想要任何限制auto也有效。

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

为什么我在此处收到“子项具有其类型使用匿名命名空间的基数”警告 的相关文章

  • 通过 CMIS (dotCMIS) 连接到 SP2010:异常未经授权

    我正在使用 dotCMIS 并且想要简单连接到我的 SP2010 服务器 我尝试用 C 来做到这一点 如下所示http chemistry apache org dotnet getting started with dotcmis htm
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co

随机推荐