繁体   English   中英

模板 (.tpp) 文件包含保护

[英]Template (.tpp) file include guards

在编写模板化类时,我喜欢将实现移动到不同的文件 ( myclass.tpp ) 并将其包含在主标题 ( myclass.hpp ) 的底部。

我的问题是:我需要包括在警卫.tpp文件还是足以让他们在.hpp文件?

示例代码:

myclass.hpp

#ifndef MYCLASS_HPP
#define MYCLASS_HPP

template<typename T>
class MyClass
{
public:
    T foo(T obj);
};

//include template implemetation
#include "myclass.tpp"

#endif

myclass.tpp

#ifndef MYCLASS_TPP //needed?
#define MYCLASS_TPP //needed?

template<typename T>
T MyClass<T>::foo(T obj)
{
    return obj;
}

#endif //needed?

我需要在 .tpp 文件中包含警卫还是将它们放在 .hpp 文件中就足够了?

永远不需要包含守卫:它们非常有用、便宜、无破坏性和预期。 所以是的,你应该用头文件保护这两个文件:

  • 非常有用:它们允许您从多个文件声明依赖项,而无需跟踪已包含哪些文件。
  • 便宜:这只是一些预编译标记。
  • 非破坏性:它们非常适合#include大多数用例(我有一位同事不知道如何编写宏,所以他#include d 实现文件facepalm )。
  • 预期:开发人员知道它们是什么并且几乎没有注意到它们; 相反,缺少 include 保护的头文件会唤醒我们并添加到全局 wtf/line 计数器中。

我借此机会强调 StoryTeller 的评论:

如果未定义 hpp 防护,我会更进一步并添加一个描述性#error指令。 只是为了提供一点保护,包括首先对人的保护。

这将转化为:

#ifndef MYCLASS_TPP
#define MYCLASS_TPP

#ifndef MYCLASS_HPP
#error __FILE__ should only be included from myclass.hpp.
#endif // MYCLASS_HPP

template<typename T>
T MyClass<T>::foo(T obj)
{
    return obj;
}

#endif // MYCLASS_TPP

注意:如果翻译单元首先#include <myclass.hpp>然后#include <myclass.tpp> ,则不会触发任何错误并且一切正常。

只需在所有头文件中使用pragma once 编译器将确保您的文件只会被包含一次。 编译器可能只会在非常不合理的情况下无法识别:有人使用硬链接构建其包含目录。 谁做这个? 如果某人找不到其文件的唯一名称,为什么他会更熟练地为所有头文件的每个包含保护找到唯一名称?

另一方面,包含保护可能会被破坏,因为宏的名称不会那么唯一,因为复制/粘贴,或者通过首先复制另一个创建的头文件等...

如何选择唯一的宏名称<project name>_<filename> 它怎么可能比基于整个根目录结构的唯一性更独特?

因此,最后,在选择 include guard 或pragma once时应考虑确保唯一性所需的工作成本:

1 - 对于pragma once您只需确保系统的目录结构不会因硬链接而混乱。

2 - 对于系统上每个文件的包含保护,您应该确保宏名称是唯一的。

我的意思是,作为一名经理,评估这项工作的成本和失败风险确实只有一种选择。 仅当不执行评估时才使用包含保护:这是一个非决定。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM