web-dev-qa-db-ja.com

C ++の概念とRustの特性の類似点と相違点は何ですか?

Rustでは、抽象化の主なツールはtraitsです。 C++には、抽象化のための2つのツール、抽象クラスとテンプレートがあります。テンプレートを使用することのいくつかの欠点(たとえば、エラーメッセージを読みにくい)を取り除くために、C++は "名前付き要件のセット" であるconceptsを導入しました。

両方の機能はかなり似ているようです

  • 特性/概念を定義するには、要件をリストします。
  • どちらも、ジェネリック/テンプレートタイプのパラメーターをバインド/制限するために使用できます。
  • Rustトレイトとコンセプトを備えたC++テンプレートはどちらもモノモーフィングされています(Rustトレイトも動的ディスパッチで使用できますが、それは別の話です)。

しかし、私が理解していることから、顕著な違いもあります。たとえば、C++の概念は、関数のシグネチャをリストする代わりに、有効でなければならない一連の式を定義しているようです。しかし、そこにはさまざまで混乱する情報がたくさんあります(たぶん、概念がC++ 20にしか着陸しないためでしょうか?)。それが私が知りたい理由です:C++の概念とRustの特性の違いと類似点は何ですか?

概念または特性のいずれかによってのみ提供される機能はありますか?例えば。 Rustの関連する型と定数についてはどうですか?または、複数の特性/概念によって型の境界を定めていますか?

42

免責事項:私はまだ概念を使用していません。それらについて知っていることはすべて、さまざまな提案やcppreferenceから収集されたものです。そのため、この答えを詳細に説明してください。

ランタイムポリモーフィズム

Rustトレイトは、コンパイル時のポリモーフィズムと実行時のポリモーフィズムの両方に使用されます。概念はコンパイル時のポリモーフィズムのみに関するものです。

構造vs公称。

概念と特性の最大の違いは、概念では構造型を使用するのに対し、特性では名義型を使用することです。

  • C++では、型は概念を明示的に満たしません。すべての要件を満たしている場合は、「誤って」満たす可能性があります。
  • Rust特定の構文構成体impl Trait for Typeを使用して、型が特性を実装することを明示的に示します。

多くの影響があります。一般に、名義型付けは保守性の観点から優れています-特性に要件を追加します-構造型タイピングは、サードパーティのライブラリをブリッジする方が優れています-ライブラリAの型は、ライブラリBの概念を満たすことができますお互いの。

制約

特性は必須です:

  • メソッドを提供する特性を実装するためにこの型が必要でない限り、ジェネリック型の変数に対してメソッドを呼び出すことはできません。

概念は完全にオプションです。

  • ジェネリック型の変数に対してメソッドを呼び出すことができます。この型は、概念を満たすために必要とされたり、何らかの制約を受けることはありません。
  • 概念または制約によってメソッドが指定されていなくても、概念(またはいくつか)を満たす一般的な型の変数でメソッドを呼び出すことができます。
  • 制約(注を参照)は完全に非定型であり、名前付きの概念を使用せずに要件を指定できます。繰り返しになりますが、これらは完全にオプションです。

注:制約はrequires句によって導入され、アドホック要件または概念に基づく要件のいずれかを指定します。

必要条件

表現可能な要件のセットは異なります。

  • 概念/制約は置換によって機能するため、言語全体を許可します。要件には、ネストされた型/定数/変数、メソッド、フィールド、別の関数/メソッドの引数として使用される能力、別の型のジェネリック引数として使用される能力、およびそれらの組み合わせが含まれます。
  • 対照的に、トレイトは、関連するタイプ/定数、メソッドなど、少数の要件のみを許可します。

オーバーロードの選択

Rustにはアドホックなオーバーロードの概念はありません。オーバーロードはトレイトによってのみ発生し、まだ特殊化はできません。

C++制約を使用して、オーバーロードを最も固有性の低いものから最も固有性の高いものに「順序付け」できるため、コンパイラーは、要件が満たされる最も固有性の高いオーバーロードを自動的に選択できます。

注:これより前は、C++でSFINAEまたはタグディスパッチングを使用して選択を実現していました。オープンエンドのオーバーロードセットを使用するには、体操が必要でした。

分離

この機能の使い方はまだはっきりしていません。

Rust=の要件メカニズムは純粋に付加的です(接続詞、別名&&)、対照的に、C++では、requires句に論理和(別名||)を含めることができます。

23
Matthieu M.