问题标签 [header-only]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
1978 浏览

c - C 中的仅标头和仅静态内联库

我在 C 中编写了仅包含头文件的小型库和仅包含static-inline的库。当应用于大型库时,这会是一个坏主意吗?还是仅使用标头版本的运行时间可能会更快?好吧,不考虑明显的编译时间差异。

0 投票
3 回答
1099 浏览

c++ - 防止 CMake 为 optional-header-only 库生成的 makefile 在仅标头模式下编译源文件

我有一个既可以用作仅标头库也可以用作传统库的库。要启用此仅可选标头功能,.cpp如果以仅标头模式编译,该库将包含源文件。例子:

当用户Vector.hpp在他/她的一个项目中包含时,如果LIBRARY_HEADERONLY定义了,实现源文件将被包含在头文件之后。谨慎使用inline关键字以避免多重定义。

如果LIBRARY_HEADERONLY未定义,.cpp则将编译文件并且必须链接库。


我选择的构建系统是CMake

使用 CMake 标志,用户可以定义或取消定义LIBRARY_HEADERONLY.

CMakeLists.txt文件类似于:


不幸的是,CMake 生成的 makefile总是编译.cpp文件,即使启用了仅标头模式并且目标是HEADER_ONLY_TARGET.

如何防止 CMake 生成的 makefile 在仅标头模式下编译源文件?

请注意,依赖于 CMake 生成的输出的 IDE(例如 Qt Creator)应将头文件和源文件都显示为项目的一部分。

如果我没有 glob 任何源文件,而只有.hpp头文件,CMake 将抱怨没有为库目标选择源文件,并且依赖于 CMake 文件的 IDE 将不会显示任何项目。

0 投票
3 回答
7136 浏览

cmake - CMake:带有生成文件的仅标头库

我有一个库,它需要携带一些从非源文件的内容(在本例中为 OpenGL 着色器代码)注入的常量数据。为了实现这一点,我使用add_custom_command()生成包含文件,然后我可以#include在我的代码中初始化 const 静态变量。

这与常规库(静态或共享)完美配合,但现在我想让我的库只包含标题。C++ 让静态方法返回静态数据而不冒在每个翻译单元中复制该数据的风险(“神奇静态”)的能力使这成为可能。

然而,问题是 CMake 似乎假设 INTERFACE 库(这是我用来创建仅标头库的 CMake 功能)不需要构建 - 在这种情况下,这是错误的。

(我意识到我的库没有实际义务仅是标头。在这种特殊情况下,我想要这样做的原因是我希望正在执行 OpenGL 的库保持独立于任何特定的绑定库 [例如GLEWorGLee或 newcomer glbinding]。通过只保留我的库标题,我可以将这个选择留给用户 - 他需要做的就是#include我之前的绑定库的标题。)

最迟在构建消费者项目时,有没有人看到让 CMake 触发生成标头的自定义命令的方法?

编辑:我刚刚意识到我可以通过保持我的库静态但仍然保留我的所有代码,除了头文件中的常量数据,我可以拥有“两全其美” 。这样,仍然不需要选择特定的 OpenGL 绑定库。但是,让一个库仅作为标头仍然有一些优势——使用起来很简单——所以我的问题是悬而未决的。

编辑#2:这是我CMakeLists.txt文件的相关部分(我只从最后剥离了库依赖项 - 所有仅标题):

0 投票
2 回答
24820 浏览

c++ - CLion 不解析来自外部库的标头

前段时间,我使用 XCode 在 C++1x 中创建了一个大型头库。库的当前布局是 () 类似于(部分输出ls -R sponf

我想将此项目移植到 CLion,这似乎是一个非常好的 IDE(基于类似的 AndroidStudio IDE),但我遇到了一些麻烦。

小测试程序

我尝试了这个小程序作为测试:

该程序编译并运行良好。但是,CLion 不识别spaces命名空间(在其中一个子文件中声明),也不识别命名simulations空间;它们都标记为红色,我无法检查它们的内容,也无法导航到它们的定义⌘</kbd>-clicking, etc. etc...

图书馆的相关部分

往里看,"sponf.h"我们发现

而在"sponf_children.h"(位于顶层,旁边"sponf.h")我们发现

然后,每个“子”标题将包含其对应的“祖先”或“类别”标题(它定义了“子”本身的超类)。

CLion的反应

尽管自动完成预测很容易找到所有子目录和头文件,但最后一个文件中的所有包含指令都被标记为红色和⌘</kbd>-clicking on any of them leads to a popup message

找不到要前往的声明

而编辑器的右侧功能区会发出许多错误信号,例如

',' 或 ) 预期

) 预期的

声明者预期

期待类型

失踪 ;

意外符号

每个包含语句都不相同(每个都生成 2 到所有这些错误)。

另一方面,CLion 完全能够找到Eigen具有几乎相同结构的所有标头!

我已将两个库都放入并进行了相应/opt/local/include更改CMakeLists.txt

为什么 CLion 不能正确解析项目结构?XCode,在包含/opt/local/include/sponf并包含/opt/local/include/eigen3HEADER_SEARCH_PATHSenv 中之后。项目的变量,能够在编译相同的确切程序时找到任何头文件。

还有什么我需要知道的吗?我做错了吗,还是 CLion 还没有那么成熟,这只是一个遗憾的错误?这是我第一次使用 CLion 和 CMake 工具链,因此任何有关它的信息都将不胜感激!

很抱歉这个很长的问题,我没有设法进一步缩小它......在此先感谢大家,很快再见!

0 投票
1 回答
712 浏览

c++ - 如何使用 CMake 从版本控制中可移植地获取仅标头库?

对于位于例如 github 上的典型 C++ 仅标头库,位于https://github.com/username/library_name

有一个目录结构,其include/library_name文件夹如下:

  • include/library_name

包含所有库资源。这通常由用户安装到,例如,在 Linux 下:/usr/local/include/library_name.

我需要一个 cmake 脚本,以便在外部项目中可移植地使用该库(跨 Linux、MacOs、BSD、Windows)。

它应该:

  • 查找是否安装了库,如果版本超过阈值,则使用已安装的库

  • 否则,从 github 获取库,将其配置为外部项目,并将其放在系统包含路径中,以便项目可以使用它,就像它已安装一样。

使用 CMake 实现这一目标的正确方法是什么?

0 投票
2 回答
1607 浏览

boost - CMake ADD_LIBRARY INTERFACE 替代品

我正在尝试使用仅标头库(线程池)作为子项目。所以在根CMakeLists.txt我有

里面thread-pool/CMakeLists.txt

由于这是一个没有源的仅标头库,因此会出错。

CMake 错误:CMake 无法确定目标的链接器语言:线程池

一种解决方案是使用ADD_LIBRARY(thread-pool INTERFACE)但仅适用于 CMake3.0并且我安装了 2.8。我不是在寻求有关如何将 CMake 升级到 3.0 的解决方案,但有什么解决方案alternative way that I can use with CMake 2.6 or 2.8吗?

我想到的一种方法是拥有一个带有一些虚拟功能的假 cpp 文件并将其放入源中,但这将是一个糟糕的解决方案。

0 投票
1 回答
1813 浏览

c++ - 编写仅标头模板库时出现“多重定义”错误

我的项目类似于这个设置,当我需要my_template_library.hmain_class.h.

主文件

main_class.h

main_class.cpp

my_template_library.h

在我编写的仅包含头文件的模板库中,我首先声明类中的所有内容,然后定义类外部的所有内容,就像您通常将类分成.h.cpp代码时所做的那样,但在.cpp末尾添加文件.h,在 include守卫。只要我的模板库只包含一次,这工作就很好,但是当它开始包含更多时,我遇到了一些非常令人困惑的问题。

我对发生了什么感到困惑。我已将其添加#pragma message到 my_template_library.h 以对此有所了解,您在此处看到代码中已将其注释掉。当我取消注释并运行我得到的代码时

所以头文件是通过以下方式包含的:

  1. main.cpp -> main_class.h
  2. main_class.h
  3. main_class.cpp -> main_class.h
  4. my_template_library.h (本身?)

所以,我的问题是:

  1. 为什么包括警卫没有帮助?
  2. 如何防止这种情况发生?
0 投票
0 回答
590 浏览

c++ - 仅标头循环依赖

我在 C++ 的仅头库中遇到了循环依赖问题,当使用源文件而不是使所有内容都成为头文件时,这不会是循环依赖问题。

情况是这样的:

两个类 A 和 B 有四个文件。每个类都有它的头文件(例如“A.hpp”)和它的实现文件(例如“A.tpp”)。

依赖关系如下:

  • A's header 需要 B' header
  • A 的 impl 需要 B 的标头
  • B 的标头只需要对 A 的前向声明
  • B 的 impl 需要 A 的标头

因此,在基于源的库中,按照以下源文件包含和编译的顺序,一切都会好起来的:

  • B.hpp
  • A.hpp
  • A.tpp 或 B.tpp(这里的顺序不重要)

我的文件的结构是这样的:

A.hpp 的文件内容:

A.tpp 的文件内容:

B.hpp 的文件内容:

B.tpp 的文件内容:

所以我的问题是:有没有一种解决方案可以打破这种不必要的循环依赖关系,这种依赖关系只是因为我为我的库使用了仅标头解决方案而发生的?

0 投票
3 回答
4869 浏览

c++ - 使用仅标头库的正确方法是什么?

我对如何正确使用仅标头库感到困惑。谷歌搜索没有帮助,因为我没有找到任何关于使用仅标头库的信息。

所以我的问题是:我应该只是复制头文件并将它们粘贴到我的项目文件夹中并以这种方式使用它们,还是应该使用 C\C++ >> General >> Additional Include Directories 将它们链接到项目?

0 投票
1 回答
1277 浏览

c++ - 内联函数编译

我打算为操作系统 API 提供简单的包装器,当错误发生时会抛出异常。这些包装器很简单,并且都被定义为头文件中的内联函数。由于系统 API 应该很大,因此头文件也应该很大,包含大量微小的内联函数。问题是,如果在包含头文件的情况下编译共享库(.so),所有这些微小的包装器会被编译成生成的二进制文件,从而导致一个大的二进制文件,即使实际上只有一小部分包装器是用过的?可执行文件的情况如何,会有所不同吗?如果是这种情况,将包装器拆分为多个头文件是唯一的解决方案吗?或者我应该通过指定使包装器内部链接static

这是我的想法。包装器可以被 ODR 使用(例如,获取其地址)。而在Linux 平台上,默认导出具有外部链接的函数(即可以被其他二进制模块链接)。所以我想链接器可能有必要为它们实际生成大纲定义。请参阅此处描述部分中的要点 3) 。

包装CloseHandle()在 Windows API 中的简单示例: