1. ホーム
  2. c++

[解決済み] ヘッダーで定義された関数やクラスをテンプレート化して実装する場合、なぜ "tpp "ファイルを使用するのですか?

2022-02-14 23:48:55

質問内容

の最初の回答をご参照ください。 テンプレートの実装に関する質問です。

具体的には、次の引用に注目してください。

これに対する一般的な解決策は、ヘッダーファイルでテンプレート宣言を書き、実装ファイルでクラスを実装することです( 例えば、.tpp ) を作成し、この実装ファイルをヘッダの末尾にインクルードします。

一番気になる部分を太字にしました。
.tppファイルの存在意義は?そのページで提案されていることをそのままやってみたところ、うまくいきました。しかし、その後、ファイルの拡張子を適当な意味不明なもの(.zzや.yppなど)に変えても、まだ動作しました 動作するようになっているのでしょうか?.tppや他の拡張子は関係ないのでしょうか?また、なぜ.cppではダメなのでしょうか?

ここでもうひとつ、迷っていることがあります。
私の実装が.cppで書かれていて、ヘッダーで非テンプレート関数が定義されている場合、.cppファイルを一回だけコンパイルする必要がありますよね? 少なくとも.cppファイルの何かを変更するまでは。

しかし、テンプレート化された関数を定義するヘッダーがあり、私の実装がランダムでファンキーな拡張子を持つファイルにある場合、それはどのようにコンパイルされるのでしょうか?そして、実装はコンパイルされるのでしょうか? あらゆる をコンパイルするとき、どのようなソースコードであっても #include のヘッダーは?

解決方法は?

<ブロッククオート

.tppなどの拡張子は関係ないのでしょうか?また、.cppではダメなのでしょうか?

拡張子は問わないが、その際に .cpp というのは、慣習に反するからです(それでも動作はしますが、やめましょう。 .cpp ファイルは一般的にソースファイルです)。 それ以外は、あなたのコードベースが何を使っているかという問題です。 例えば、私(とBoostコードベース)は以下のように使っています。 .ipp を使用します。

<ブロッククオート

.tppファイルの存在意義は?

あるモジュールのインターフェイスを含むファイルに、血なまぐさい実装の詳細をすべて記載したくない場合に使用します。 しかし、実装を .cpp ファイルはテンプレートだからです。 そこで、できる限りのことをするわけです(明示的なインスタンス化などは考慮しない)。 例えば

Something.hpp

#pragma once

namespace space {

template <typename Type>
class Something {
public:
    void some_interface();
};

} // namespace space

#include "Something.ipp"

Something.ipp

#pragma once

namespace space {

template <typename Type>
void Something<Type>::some_interface() {
    // the implementation
}

} // namespace space


ヘッダーに定義、別ファイルに実装を書くのは、コンパイル時間を短縮するためで、実装を変更するまでは一度だけコンパイルすればよいと思っていました。

一般的なテンプレートコードを実装ファイルに分割することはできません。 テンプレートを使用するためには、全コードを表示する必要があります。 詳しくは、以下を参照してください。 なぜテンプレートはヘッダーファイルでしか実装できないのですか?

<ブロッククオート

しかし、実装ファイルに何かおかしな拡張子がついていた場合、コンパイルの面ではどうなのでしょうか?実装がcppにある場合と同じように効率的なのでしょうか?

をコンパイルしないんですね。 .tpp , .ipp , -inl.h などのファイルです。 これらは、他のヘッダーファイルによってのみインクルードされることを除けば、ヘッダーファイルと同じです。 コンパイルするのはソースだけです ( .cpp , .cc ) ファイルを作成します。