web-dev-qa-db-ja.com

#includeディレクティブでファイル拡張子を省略できるのはいつですか?

Gmockで遊んでいると、次の行が含まれていることに気付きました。

#include <Tuple>

私はTuple.hを期待していたでしょう。

拡張機能を除外しても問題がないのはいつですか。また、ディレクティブに別の意味を与えますか?

44
Gordon Wilson

C++標準ヘッダーには、「。h」サフィックスがありません。その理由は、標準が破られるであろう多くの異なる事前標準の実装があったからだと思います。そのため、ベンダーが既存の「iostream.h」(たとえば)ヘッダーを標準に準拠するように変更することを要求する代わりに(既存のユーザーのコードを破壊する)、標準委員会はサフィックスを削除することを決定しました(これはその後、既存の実装はすでに実行されていました)。

そうすれば、既存の非標準プログラムは、ベンダーの非標準ライブラリを使用して引き続き機能します。ユーザーがプログラムを標準に準拠させたい場合、実行する手順の1つは、「#include」ディレクティブを変更して「.h」サフィックスを削除することです。

そう

#include <iostream>     // include the standard library version
#include <iostream.h>   // include a vendor specific version (which by 
                        //      now might well be the same)

他の回答が述べているように、非標準ライブラリの作成者はどちらの命名規則も選択できますが、いくつかの理由から、「。h」または「.hpp」(Boostが行ったように)を使い続けたいと思います。

  1. ライブラリが標準化された場合、標準バージョンは以前の非標準バージョンを自動的にオーバーライドしません(おそらくユーザーコードが壊れます)
  2. 接尾辞のないヘッダーは標準ライブラリであり、接尾辞のあるヘッダー(古いCヘッダー以外)は非標準であるというのは(多かれ少なかれ)慣例のようです。

委員会がSTLにハッシュマップを追加しようとしたときに同様の問題が発生したことに注意してください-彼らはすでに多くの(異なる)hash_map実装が存在することを発見したので、多くを壊す標準的なものを考え出す代わりに今日そこにあるものの中で、彼らは標準実装を「unordered_map」と呼んでいます。名前空間は、このタイプのフープを飛び越えるのを防ぐのに役立つはずでしたが、多くのコードを壊さずに、より自然な名前を使用できるように十分に機能していない(または十分に使用されていない)ようです。

'C'ヘッダーの場合、C++では<cxxxxxx>または<xxxxxx.h>バリアントのいずれかを含めることができることに注意してください。 'c'で始まり、 "。h"接尾辞がないものは、宣言をstd名前空間(および場合によってはグローバル名前空間)に配置し、 "。h"接尾辞が付いているものは名前をグローバル名前空間(一部のコンパイラは名前をstd名前空間にも入れます-害はないと思いますが、それが標準に準拠しているかどうかはわかりません)。

63
Michael Burr

ファイルの名前がTupleの場合は、#include <Tuple>する必要があり、Tuple.hの名前の場合は、#include <Tuple.h>する必要があります。

それはそれと同じくらい簡単です。拡張子を省略していません。

18
Ferruccio

単に「Tuple」という名前のファイルが含まれています。ファイル自体に拡張子がありません。

C++インクルードファイルの推定標準は、.h拡張子なしでファイルに名前を付けることです。多くのライブラリライターはこの標準(STLなど)に準拠していますが、準拠していないものもあります。

15
Crashworks

特別なことは何も起こっていません。このファイルの名前は単にTupleです。

この理由は...標準ライブラリヘッダーにファイル拡張子がないのは、namespacesが原因です。

名前空間は、ゲームの後半にC++ 98標準でC++標準に追加されました。これには、すべての標準ライブラリエンティティが存在するstd名前空間が含まれます。

標準ライブラリがstd名前空間に移動されたとき、それはすべての既存のC++コードが、ライブラリがグローバル名前空間にあることを期待していたために壊れることを意味しました。解決策は、古い「dot-h」ヘッダーファイルをそのままにして、拡張子のないファイルで名前空間ライブラリを提供することでした。

このように、#include<iosteam.h>である古いコードはグローバルcoutを期待でき、新しいコードは#include<iostream>std::coutを期待できます。

7
Drew Dormann

すでに投稿されている細かい回答に加えて、C++標準では、「iostream」または「iostream.h」という名前のファイルを読み取るためにディレクティブ「#include<iostream>」は必要ないことに注意してください。それは「ファズボール」と名付けることができます。または、対応するファイルが存在せず、定義がコンパイラーに組み込まれ、includeディレクティブによってアクティブ化される場合があります。

4
Darron

私の理解では、#includeTupleはTuple.hを「指す」ということでした。

これをチェックしてください: iostream vs iostream.h

4
nmiller