1. ホーム
  2. c++

[解決済み】C++のSTLはなぜテンプレートに大きく依存しているのですか?(そして*インターフェイス*にはない)

2022-04-17 21:36:45

質問

つまり、その義務的な名前(Standard Template Library)はともかくとして...。

つまり、クラスとクラス階層に基づいて、特定のエンティティに何ができて何ができないか(それがどのように行われるかは別として)を知ることができるのです。能力の構成によっては、多重継承の問題や、C++がインターフェースの概念を(javaなどに比べて)やや不器用な方法でサポートしているために、この方法で記述するのはより困難ですが、それは存在します(そして改善される可能性もあります)。

そして、STLとともにテンプレートが登場しました。STLは、古典的なOOPの概念を取り去って排水溝に流し、代わりにテンプレートを使用するようになったようです。

テンプレートを使って型を一般化する場合、その型自体がテンプレートの動作に無関係な場合(例えばコンテナ)と区別する必要があります。例えば vector<int> は完全に理にかなっています。

しかし、他の多くの場合(イテレータやアルゴリズム)、テンプレート化された型は "concept"(入力イテレータ、前進イテレータ、など)に従うことになっており、実際のコンセプトの詳細はテンプレート関数/クラスの実装によってすべて定義され、テンプレートで使用する型のクラスには定義されないという、OOPのやや反目的の使用方法になっています。

例えば、関数を伝えることができます。

void MyFunc(ForwardIterator<...> *I);

更新しました。 元の質問で不明だったのですが、ForwardIteratorはそれ自体をテンプレート化して任意のForwardIterator型を許容するのはOKです。逆に言えば、ForwardIteratorを概念として持っていることです。

は、その定義を見るだけで、Forward Iterator を期待することができ、実装かドキュメントを見る必要があります。

template <typename Type> void MyFunc(Type *I);

それは、vtablesを使う代わりに、使用する型ごとにテンプレートをオーダーメイドでコンパイルすることによって、コンパイルされたコードをより効率的にすることができるということです。そして、テンプレートはネイティブな型と一緒に使うことができるということです。

しかし、なぜ古典的なOOPを捨てて、STLのテンプレート化に賛成するのか、もっと深い理由を探しているのです。(ここまで読んでくれたとして:P)

解決方法は?

簡単に言うと、「C++が進歩したから」です。確かに70年代後半、StroustrupはOOPの機能を持つアップグレードしたCを作ろうとしましたが、それはずいぶん前のことです。1998年に標準化された時点で、C++はもはやOOP言語ではなくなりました。マルチパラダイム言語だったのです。確かにOOPコードのサポートはありましたが、チューリング完全なテンプレート言語が重なっており、コンパイル時のメタプログラミングが可能で、ジェネリックプログラミングも発見されていました。突然、OOPがそれほど重要でないように思えてきたのです。もっとシンプルで簡潔な テンプレートやジェネリック・プログラミングの技術を使うことで、より効率的なコードを作成することができます。

OOPは聖杯ではありません。かわいいアイデアだし、70年代に発明された当時は手続き型言語に比べてかなり改善された。しかし、正直なところ、それがすべてではありません。多くの場合、不器用で冗長であり、再利用可能なコードやモジュール性を促進するものではありません。

そのため、C++コミュニティは今日、ジェネリック・プログラミングにはるかに多くの関心を寄せており、また、なぜ みんな 関数型プログラミングもかなり賢いということにようやく気づき始めたようです。OOP単体では、きれいごとでは済まないのです。

OOP化されたSTLを仮定して依存関係グラフを描いてみてください。どれだけのクラスが互いのことを知らなければならないでしょうか?そこには ロット の依存関係がある。だけを含めることができるでしょうか? vector ヘッダを取得することなく iterator あるいは iostream が引っ張られた?STLはこれを簡単にします。ベクトルはそれが定義するイテレータ型について知っている、ただそれだけです。STLのアルゴリズムが知っているのは 何もない . これらはすべてパラメータとしてイテレータを受け取るにもかかわらず、イテレータヘッダを含める必要さえない。では、どちらがよりモジュール化されているのでしょうか?

STLは、Javaが定義するOOPのルールには従っていないかもしれませんが、その分 目標 OOPの?再利用性、低結合性、モジュール性、カプセル化などが実現されていないのでしょうか?

また、次のような目標も達成できるのではないでしょうか。 より良い OOP化されたバージョンよりも?

なぜSTLが言語に採用されたかというと、いくつかのことがきっかけでSTLになったんです。

まず、C++にテンプレートが追加されました。これは、.NETにジェネリックが追加されたのとほぼ同じ理由で追加されました。型安全性を捨てることなく、「T"型のコンテナ」のように書けるのは良いアイデアだと思ったのです。もちろん、最終的に採用された実装は、もっとずっと複雑で強力なものでした。

そして、追加したテンプレートの仕組みが予想以上に強力であることに気づいた人たちがいました。そして、テンプレートを使って、より汎用的なライブラリを書こうと実験する人が現れました。関数型プログラミングに触発され、C++の新機能をすべて使ったものです。

C++言語委員会に提出したところ、あまりの違和感に慣れるまでかなり時間がかかったが、最終的に以下のことに気がついたという。 従来のOOPに相当するものを入れるよりも、より効果的なのです。 . そこで、いくつかの調整を行い、標準ライブラリに採用したのです。

それはイデオロギー的な選択ではなく、「OOPにするかしないか」という政治的な選択でもなく、非常に現実的なものでした。彼らはライブラリを評価し、それが非常にうまく機能していることを確認したのです。

いずれにせよ、あなたがおっしゃるSTLを支持する理由は、どちらも絶対に必要なものです。

C++の標準ライブラリ があります。 は効率的でなければなりません。もしそれが、例えば同等のハンドロールCコードよりも効率が悪いのであれば、人々はそれを使わないでしょう。生産性が低下し、バグが発生しやすくなり、全体として悪い考えとなります。

そしてSTL があります。 というのも、C言語にはプリミティブ型しかなく、どちらの言語でもプリミティブ型は重要な位置を占めているからです。もしSTLがネイティブな配列を扱えなかったら、それはもう 無駄 .

この質問には、OOPがベストであるという強い前提があります。その理由をお聞かせください。あなたは、なぜ彼らが古典的なOOPを放棄したのかと尋ねています。私は、なぜ彼らがそれに固執する必要があったのかが気になります。どのような利点があったのでしょうか?