首页 > 解决方案 > glm 如何避免在另一个(未连接的?)文件中声明一个函数内联并内联定义它?

问题描述

glm 有一些看起来像这样的代码,一旦在我的特定设置上解析了预处理器宏:

type_vec3.hpp

struct vec3
{
    /*...*/
    vec3& operator=(vec3 const & v);
    /*...*/
}

type_vec3.inl

inline vec3& vec3::operator=(vec3 const & v)
{ /* implementation */ }

我在 .inl 文件中找不到任何相关的标头。当我尝试用这种布局重写时,我会得到链接器错误(我认为这是由于头文件声明和inline-specified 定义不匹配)或命名空间问题(如果头文件不包含在 inl 文件中) .

这是 GitHub 上的 glm:https ://github.com/g-truc/glm 。有问题的文件在这里:

https://github.com/g-truc/glm/blob/master/glm/detail/type_vec3.hpp(L179

https://github.com/g-truc/glm/blob/master/glm/detail/type_vec3.inl(L214

这两个文件中包含的标头在我使用的 glm 版本中不存在,这似乎表现良好。

有人可以解释一下这里发生了什么吗?

标签: c++glm-math

解决方案


这只是将实现和声明拆分为单独文件的一种方式。.hpp文件声明vec3,然后是#include文件.inl(除非请求了非内联版本)。很容易错过#include结尾处的.hpp,但它就在那里。尽管声称文件未连接,但它们是连接的,尽管方向与预期相反。

(大概,如果GLM_EXTERNAL_TEMPLATE定义了,定义vec3::operator=将在单独的组件中提供,而不是作为内联函数。)

另一个值得注意的方面是这些文件位于一个名为“detail”的目录中。这是一个约定,表示这些文件如有更改,恕不另行通知。特别是,它们可能不存在于旧版本中。(它们也可能不存在于较新的版本中,但当您查看最新版本时,这更像是一个学术点。)

因此,总体情况是您#include是正常的头文件之一,它将确保两者type_vec3.hpptype_vec3.inl#include顺序排列。这将内联定义放在具有vec3声明的每个翻译单元中。


推荐阅读