web-dev-qa-db-ja.com

テンプレート(.tpp)ファイルにはガードが含まれています

テンプレート化されたクラスを作成するときは、実装を別のファイル(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?
14
dave

ガードを.tppファイルに含める必要がありますか、それとも.hppファイルに含めるだけで十分ですか?

インクルードガードは決して必要ありません:それらは非常に便利で、安価で、中断がなく、期待されています。そうです、両方のファイルをヘッダーガードで保護する必要があります。

  • 非常に便利:どのファイルがすでに含まれているかを追跡せずに、複数のファイルからの依存関係を宣言できます。
  • 安い:これはいくつかのプリコンパイルトークンです。
  • 非破壊的:それらは#includeのほとんどのユースケースにうまく適合します(マクロの書き方を知らない同僚がいたので、彼は#included実装ファイル* facepalm *)。
  • 期待される:開発者は彼らが何であるかを知っており、ほとんど気づいていません。それどころか、インクルードガードが欠落しているヘッダーファイルは、私たちを起こしてグローバルwtf/lineカウンターに追加します。

StoryTellerからのコメントを強調する機会を利用します。

Hppガードが定義されていない場合は、さらに一歩進んで、説明的な#errorディレクティブを追加します。最初にtppを含む人々から少し保護を提供するためだけに。

これは次のように解釈されます。

#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>の場合、エラーは発生せず、すべてが正常です。

14
YSC

すべてのヘッダーファイルでpragma onceを使用するだけです。コンパイラは、ファイルが1回だけ含まれるようにします。コンパイラは、非常に不合理な状態でのみ認識に失敗する可能性があります。誰かがハードリンクを使用してインクルードディレクトリを構築します。これは誰ですか?誰かがそのファイルの一意の名前を見つけることができない場合、なぜ彼はすべてのヘッダーファイルの各インクルードガードの一意の名前を見つけるのに熟練しているのでしょうか?

一方、インクルードガードは、マクロの名前がそれほど一意ではないため、コピー/貼り付け、または最初に他のファイルをコピーして作成されたヘッダーファイルなどのために壊れている可能性があります...

一意のマクロ名<project name>_<filename>はどのように選択されますか?ルートディレクトリ構造全体に基づく一意性よりも、どのように一意である可能性がありますか?

したがって、最終的には、インクルードガードまたはpragma onceのどちらかを選択するときに、一意性を確保するために必要なジョブのコストを考慮する必要があります。

1-pragma onceの場合、ハードリンクのおかげでシステムの構造化されたディレクトリが台無しになっていないことを確認するだけで済みます。

2-For include guardシステム上の各ファイルについて、マクロ名が一意であることを確認する必要があります。

私はマネージャーとして、この仕事のコストと失敗のリスクを評価することは、1つの選択肢しか許さないことを意味します。インクルードガードは、評価が実行されない場合にのみ使用されます。これは決定ではありません。

3
Oliv