テンプレート化されたクラスを作成するときは、実装を別のファイル(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 *)。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>
の場合、エラーは発生せず、すべてが正常です。
すべてのヘッダーファイルでpragma once
を使用するだけです。コンパイラは、ファイルが1回だけ含まれるようにします。コンパイラは、非常に不合理な状態でのみ認識に失敗する可能性があります。誰かがハードリンクを使用してインクルードディレクトリを構築します。これは誰ですか?誰かがそのファイルの一意の名前を見つけることができない場合、なぜ彼はすべてのヘッダーファイルの各インクルードガードの一意の名前を見つけるのに熟練しているのでしょうか?
一方、インクルードガードは、マクロの名前がそれほど一意ではないため、コピー/貼り付け、または最初に他のファイルをコピーして作成されたヘッダーファイルなどのために壊れている可能性があります...
一意のマクロ名:<project name>_<filename>
はどのように選択されますか?ルートディレクトリ構造全体に基づく一意性よりも、どのように一意である可能性がありますか?
したがって、最終的には、インクルードガードまたはpragma once
のどちらかを選択するときに、一意性を確保するために必要なジョブのコストを考慮する必要があります。
1-pragma once
の場合、ハードリンクのおかげでシステムの構造化されたディレクトリが台無しになっていないことを確認するだけで済みます。
2-For include guardシステム上の各ファイルについて、マクロ名が一意であることを確認する必要があります。
私はマネージャーとして、この仕事のコストと失敗のリスクを評価することは、1つの選択肢しか許さないことを意味します。インクルードガードは、評価が実行されない場合にのみ使用されます。これは決定ではありません。