简体   繁体   English

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

[英]Template (.tpp) file include guards

When writing templated classes, I like to move the implementation into a different file ( myclass.tpp ) and include it at the bottom of the main header ( myclass.hpp ).在编写模板化类时,我喜欢将实现移动到不同的文件 ( myclass.tpp ) 并将其包含在主标题 ( myclass.hpp ) 的底部。

My Question is: do I need include guards in the .tpp file or is it sufficient to have them in the .hpp file?我的问题是:我需要包括在警卫.tpp文件还是足以让他们在.hpp文件?

Example code:示例代码:

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?

Do I need include guards in the .tpp file or is it sufficient to have them in the .hpp file?我需要在 .tpp 文件中包含警卫还是将它们放在 .hpp 文件中就足够了?

Include guards are never needed : they're just terribly useful, cheap, non-disruptive and expected.永远不需要包含守卫:它们非常有用、便宜、无破坏性和预期。 So Yes, you should protect both files with header guards:所以是的,你应该用头文件保护这两个文件:

  • Terribly useful : they allow you to declare a dependency from multiple files without keeping track of which files have already been included.非常有用:它们允许您从多个文件声明依赖项,而无需跟踪已包含哪些文件。
  • Cheap : this is just some precompilation tokens.便宜:这只是一些预编译标记。
  • Non-disruptive : they fit well with most use-cases of #include (I've had a colleague who didn't know how to write macros so he #include d implementation files facepalm ).非破坏性:它们非常适合#include大多数用例(我有一位同事不知道如何编写宏,所以他#include d 实现文件facepalm )。
  • Expected : developers know what they are and barely notice them;预期:开发人员知道它们是什么并且几乎没有注意到它们; on the contrary a header file missing include guards wakes us up and adds to the global wtf/line counter.相反,缺少 include 保护的头文件会唤醒我们并添加到全局 wtf/line 计数器中。

I take the opportunity to highlight the comment from StoryTeller:我借此机会强调 StoryTeller 的评论:

I'd go a step further and add a descriptive #error directive if the hpp guard is not defined.如果未定义 hpp 防护,我会更进一步并添加一个描述性#error指令。 Just to offer a little protection from people including the tpp first.只是为了提供一点保护,包括首先对人的保护。

Which will translate to:这将转化为:

#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

Notice: if a translation unit first #include <myclass.hpp> and then #include <myclass.tpp> , no error is fired and everything is fine.注意:如果翻译单元首先#include <myclass.hpp>然后#include <myclass.tpp> ,则不会触发任何错误并且一切正常。

Just use pragma once in all headers file.只需在所有头文件中使用pragma once The compiler will ensure your file will be included only once.编译器将确保您的文件只会被包含一次。 The compiler may only fail to recognize in very unreasonable condition: someone structure its include directories using hard-link.编译器可能只会在非常不合理的情况下无法识别:有人使用硬链接构建其包含目录。 Who does this?谁做这个? If someone cannot find a unique name for its file, why would he be more skilled to find a unique name for each include guard for all the header files?如果某人找不到其文件的唯一名称,为什么他会更熟练地为所有头文件的每个包含保护找到唯一名称?

On the other hand, include guard may be broken because the name of the macro will not be that unique, because of a copy/paste, or a header file created by first copying an other, etc...另一方面,包含保护可能会被破坏,因为宏的名称不会那么唯一,因为复制/粘贴,或者通过首先复制另一个创建的头文件等...

How are chosen the unique macro name : <project name>_<filename> ?如何选择唯一的宏名称<project name>_<filename> How could it be more unique than a uniqueness based on the entire root directory structure?它怎么可能比基于整个根目录结构的唯一性更独特?

So in the end, one should consider when choosing between include guard or pragma once , the cost of the job that is necessary to ensure uniqueness:因此,最后,在选择 include guard 或pragma once时应考虑确保唯一性所需的工作成本:

1 - For pragma once you only have to ensure that the directory structured of your system is not messed-out thanks to hard links. 1 - 对于pragma once您只需确保系统的目录结构不会因硬链接而混乱。

2 - For include guard for each file on your system you should ensure that the macro name is unique. 2 - 对于系统上每个文件的包含保护,您应该确保宏名称是唯一的。

I mean as a manager, evaluating the cost of this job and the failure risk does let only one option.我的意思是,作为一名经理,评估这项工作的成本和失败风险确实只有一种选择。 Include guard are used only when no evaluation is performed: it is a non decision.仅当不执行评估时才使用包含保护:这是一个非决定。

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

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