web-dev-qa-db-ja.com

コンセプトとテンプレート制約の違いは何ですか?

C++の完全な概念の提案とテンプレートの制約(たとえば、Dlangまたは C++ 1yの新しいconcept-liteの提案 )に見られる制約のセマンティックな違いを知りたいです。

テンプレートの制約ではできない以上のことができる本格的なコンセプトは何ですか?

95
Rayniery

次の情報は古くなっています。最新のConcepts Liteドラフトに従って更新する必要があります。

制約の提案 のセクション3は、これを妥当な深さでカバーしています。

概念の提案 制約(概念-lite)がより短い時間スケールで肉付けされ、実装され、現在少なくとも何かを目指していることを期待して、しばらくの間バックバーナーに置かれましたC++ 14で。制約の提案は、後の概念の定義へのスムーズな移行として機能するように設計されています。制約はの一部概念の提案であり、その定義に必要な構成要素です。

C++のコンセプトライブラリの設計 では、SuttonとStroustrupは次の関係を考慮します。

概念=制約+公理

それらの意味をすばやく要約するには:

  1. 制約-型の静的に評価可能なプロパティの述語。純粋に構文上の要件。ドメインの抽象化ではありません。
  2. 公理-真であると想定されるタイプの意味要件。静的にチェックされていません。
  3. 概念-引数に関するアルゴリズムの一般的な抽象的な要件。制約と公理の観点から定義されています。

そのため、制約(構文プロパティ)に公理(意味プロパティ)を追加すると、概念が得られます。


コンセプトライト

コンセプトライトの提案は、最初の部分である制約のみをもたらしますが、これは本格的なコンセプトに向けた重要かつ必要なステップです。

制約

制約はすべてsyntaxについてです。コンパイル時に型のプロパティを静的に識別する方法を提供するため、構文のプロパティに基づいてテンプレート引数として使用される型を制限できます。制約の現在の提案では、それらは&&||のような論理接続詞を使用した命題計算のサブセットで表現されています。

実際の制約を見てみましょう。

template <typename Cont>
  requires Sortable<Cont>()
void sort(Cont& container);

ここでは、sortという関数テンプレートを定義しています。新しい追加はrequires句です。 require節は、この関数のテンプレート引数に対していくつかの制約を与えます。特に、この制約は、タイプContSortableタイプでなければならないことを示しています。すてきなことは、より簡潔な形式で次のように記述できることです。

template <Sortable Cont>
void sort(Cont& container);

Sortableと見なされないものをこの関数に渡そうとすると、Tに対して推定される型がSortableタイプ。 C++ 11でこれを行っていた場合、inside誰にも意味のないsort関数からいくつかの恐ろしいエラーがスローされたでしょう。

制約述語は型特性に非常に似ています。彼らはいくつかのテンプレート引数タイプを取り、あなたにそれに関するいくつかの情報を与えます。制約は、タイプに関する次の種類の質問に答えようとします。

  1. このタイプには、そのような演算子がオーバーロードされていますか?
  2. これらの型は、この演算子のオペランドとして使用できますか?
  3. このタイプにはそのような特徴がありますか?
  4. この定数式はそれに等しいですか? (非型テンプレート引数の場合)
  5. この型には、その型を返すyada-yadaという関数がありますか?
  6. このタイプは、それとして使用されるすべての構文要件を満たしていますか?

ただし、制約はreplace型の特性を意図したものではありません。代わりに、彼らは手をつないで動作します。一部のタイプ特性は、概念の観点から定義できるようになり、一部のコンセプトは、タイプ特性の観点から定義できるようになりました。

そのため、制約に関する重要なことは、セマンティクスが1つのイオタに関係ないことです。制約の良い例は次のとおりです。

  • Equality_comparable<T>:型に==があり、その同じ型の両方のオペランドがあるかどうかを確認します。

  • Equality_comparable<T,U>:指定されたタイプの左右のオペランドを持つ==があるかどうかを確認します

  • Arithmetic<T>:型が算術型かどうかを確認します。

  • Floating_point<T>:型が浮動小数点型かどうかを確認します。

  • Input_iterator<T>:入力イテレーターがサポートしなければならない構文操作をタイプがサポートしているかどうかを確認します。

  • Same<T,U>:指定されたタイプが同じかどうかを確認します。

特別な GCCのconcepts-liteビルド を使用して、これらすべてを試すことができます。


概念を超えて-ライト

今、私たちはconcepts-lite提案を超えてすべてに入ります。これは未来そのものよりも未来的です。 ここから先はすべてかなり変わる可能性が高い。

公理

公理はすべて意味論に関連しています。これらは、関係、不変式、複雑性の保証などを指定します。例を見てみましょう。

Equality_comparable<T,U>制約は、タイプTおよびUをとるoperator==があることを示しますが、その操作meansを示しません。そのために、公理Equivalence_relationがあります。この公理は、これら2つのタイプのオブジェクトをoperator==と比較してtrueを与える場合、これらのオブジェクトは同等であると言います。これは冗長に見えるかもしれませんが、そうではありません。代わりにoperator==のように動作するoperator<を簡単に定義できます。あなたはそれをするのは悪でしょうが、できます。

別の例はGreater公理です。タイプTの2つのオブジェクトを>および<演算子と比較できると言ってもいいですが、それらは何ですかmeanGreater公理は、xyより大きい場合、yxより小さい場合に限ります。公理などの提案された仕様は次のようになります。

template<typename T>
axiom Greater(T x, T y) {
  (x>y) == (y<x);
}

したがって、公理は次のタイプの質問に答えます。

  1. これら2つの演算子は互いにこの関係を持っていますか?
  2. そのようなタイプのこの演算子はこれを意味しますか?
  3. そのタイプのこの操作にはこの複雑さがありますか?
  4. その演算子のこの結果は、これが真実であることを意味しますか?

つまり、それらは完全に型のセマンティクスとそれらの型の操作に関係しています。これらを静的にチェックすることはできません。これをチェックする必要がある場合、型は何らかの方法でこれらのセマンティクスに従うことを宣言する必要があります。

公理の一般的な例を次に示します。

  • Equivalence_relation:2つのオブジェクトが==を比較する場合、それらは同等です。

  • Greaterx > yのたびに、y < x

  • Less_equalx <= yのときはいつでも、!(y < x)

  • Copy_equality:タイプxyおよびTの場合:x == yの場合、コピー構築T{x} == yによって作成された同じタイプの新しいオブジェクトであり、それでもx == y(つまり、non -破壊的)。

コンセプト

現在、概念の定義は非常に簡単です。それらは単純に制約と公理の組み合わせです。これらは、型の構文およびセマンティクスに対する抽象要件を提供します。

例として、次のOrderedの概念を検討してください。

concept Ordered<Regular T> {
  requires constraint Less<T>;
  requires axiom Strict_total_order<less<T>, T>;
  requires axiom Greater<T>;
  requires axiom Less_equal<T>;
  requires axiom Greater_equal<T>;
}

最初に、テンプレートタイプTOrderedにするには、Regularコンセプトの要件も満たしている必要があります。 Regularコンセプトは、型が適切に動作するための非常に基本的な要件です-構築、破棄、コピー、および比較が可能です。

これらの要件に加えて、OrderedTが1つの制約と4つの公理を満たすことを要求します。

  • 制約:Ordered型にはoperator<が必要です。これは静的にチェックされるため、mustが存在します。
  • 公理:タイプx:のyおよびTの場合
    • x < yは、厳密な合計順序付けを提供します。
    • xyより大きい場合、yxより小さい、またはその逆です。
    • xy以下である場合、yx以上であり、その逆も同様です。
    • xy以上の場合、yx以下であり、その逆も同様です。

このように制約と公理を組み合わせると、概念が得られます。これらは、アルゴリズムで使用する抽象型の構文要件および意味要件を定義します。アルゴリズムは現在、使用されているタイプが特定の操作をサポートし、特定のセマンティクスを表現すると想定する必要があります。コンセプトにより、要件が満たされていることを確認できます。

最新の概念設計 では、コンパイラは、テンプレート引数によって概念の構文要件が満たされていることのみをチェックします。公理は未チェックのままです。公理は静的に評価できない(または完全にチェックできないことが多い)セマンティクスを示すため、型の作成者は、その型が概念のすべての要件を満たしていることを明示的に述べる必要があります。これは、以前の設計ではコンセプトマッピングとして知られていましたが、その後削除されました。

概念の例を次に示します。

  • Regular型は、構築可能、破壊可能、コピー可能、および比較可能です。

  • Ordered型はoperator<をサポートし、厳密な合計順序付けおよびその他の順序付けセマンティクスを備えています。

  • Copyable型はコピー可能、破壊可能です。xyと等しく、xがコピーされる場合、コピーもy

  • Iteratorタイプには、関連するタイプvalue_typereferencedifference_type、およびiterator_categoryが必要です。これらは、特定の概念を満たす必要があります。また、operator++をサポートし、逆参照可能でなければなりません。

概念への道

制約は、C++の完全な概念機能に向けた最初のステップです。型の静的に強制可能な要件を提供するため、非常に重要なステップであり、よりクリーンなテンプレート関数とクラスを作成できます。これで、std::enable_ifとそのメタプログラミングの友人の困難とさのいくつかを回避できます。

ただし、制約の提案ではできないことがいくつかあります。

  1. 概念定義言語は提供しません。

  2. 制約は概念マップではありません。ユーザーは、特定の制約を満たしているとタイプを明確に注釈する必要はありません。これらは、単純なコンパイル時言語機能を使用して静的にチェックされます。

  3. テンプレートの実装は、テンプレート引数の制約によって制約されません。つまり、関数テンプレートが、実行すべきではない制約型のオブジェクトを使用して何かを行う場合、コンパイラーはそれを診断する方法がありません。完全な機能を備えた概念の提案により、これが可能になります。

制約の提案は、その上に完全な概念の提案を導入できるように特別に設計されています。運が良ければ、その移行はかなりスムーズに行われるはずです。コンセプトグループは、C++ 14(またはその後まもなくテクニカルレポート)に制約を導入することを検討していますが、C++ 17の前後に完全なコンセプトが出現し始める可能性があります。

133

また、同じ日に投稿された最近の(3月12日)Conceptsテレコン議事録とディスカッションの記録のセクション2.3の「概念liteについての「ライト」とは」も参照してください。 http://isocpp.org/blog/2013/03/new-paper-n3576-sg8-concepts-teleconference-minutes-2013-03-12-herb-sutter

22
Herb Sutter

私の2セント:

  1. Concepts-Liteの提案は、テンプレートの「型チェック」を行うことを意図したものではありません実装。つまり、Concepts-liteは、テンプレートのインスタンス化サイトで(概念的に)インターフェイスの互換性を確保します。論文からの引用:「concepts liteは、テンプレート引数を制約する述語の使用を可能にするC++の拡張機能です」。以上です。テンプレート本体が述部に対して(単独で)チェックされるとは言いません。それはおそらく、concepts-liteについて話しているときにarchtypesのファーストクラスの概念がないことを意味します。私が正しく覚えていれば、概念の中で、archtypesは、テンプレートのimplementationを満たすために、それ以上でもそれ以上でもないタイプです。

  2. concepts-Liteは、コンパイラーがサポートする少しの構文トリックを使用して、洗練されたconstexpr関数を使用します。ルックアップルールに変更はありません。

  3. プログラマーは概念マップを書く必要はありません。

  4. 最後に、「制約の提案は、セマンティクスの仕様または使用に直接対処するものではありません。構文のチェックのみを対象としています。」これは、公理が範囲内にないことを意味します(これまで)。

4
Sumant