99

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

テンプレートの制約よりも実行できる本格的な概念は何ですか?

4

3 に答える 3

139

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

制約提案のセクション 3 では、これについて妥当な深さで説明しています。

概念の提案は、制約 (つまり、concepts-lite) をより短い時間スケールで具体化して実装できることを期待して、しばらく後回しにされました。現在、少なくとも C++14 で何かを目指しています。制約の提案は、概念の後の定義へのスムーズな移行として機能するように設計されています。制約は概念提案の一部であり、その定義に必要なビルディング ブロックです。

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

概念 = 制約 + 公理

それらの意味を簡単に要約するには:

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

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


コンセプトライト

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

制約

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

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

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

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

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

この関数に考慮されていないものを渡そうとすると、推定された型が型ではないSortableことをすぐに知らせる素敵なエラーが表示されます。これを C++11 で行っていたら、関数から何の意味もない恐ろしいエラーがスローされていたでしょう。TSortablesort

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

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

ただし、制約は型特性を置き換えることを意図したものではありません。代わりに、彼らは手を取り合って働きます。一部の型特性は概念の観点から定義でき、一部の概念は型特性の観点から定義できるようになりました。

したがって、制約に関する重要なことは、それらがセマンティクスを 1 イオタ気にしないということです。制約の良い例は次のとおりです。

  • Equality_comparable<T>==処置: タイプが同じタイプの両方のオペランドを持つかどうかをチェックします。

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

  • Arithmetic<T>: 型が算術型かどうかをチェックします。

  • Floating_point<T>: 型が浮動小数点型かどうかをチェックします。

  • Input_iterator<T>: 入力反復子がサポートする必要がある構文操作を型がサポートしているかどうかを確認します。

  • Same<T,U>: 指定された型が同じかどうかをチェックします。

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


Beyond Concepts-Lite

ここで、concepts-lite の提案を超えたすべての作業に入ります。これは、未来そのものよりもさらに未来的です。これからのすべてがかなり変わる可能性があります。

公理

公理はセマンティクスに関するものです。それらは、関係、不変条件、複雑さの保証などを指定します。例を見てみましょう。

型を 取ると があることはEquality_comparable<T,U>制約からわかりますが、その操作が何を意味するかはわかりません。そのために、公理があります。この公理は、これら 2 つのタイプのオブジェクトが を与えることと比較される場合、これらのオブジェクトは同等であると述べています。これは冗長に思えるかもしれませんが、決してそうではありません。のように動作する を簡単に定義できます。あなたはそれをするのは悪いことですが、できます。operator==TUEquivalence_relationoperator==trueoperator==operator<

別の例はGreater公理です。型の 2 つのオブジェクトをand演算子Tと比較できると言っても過言ではありませんが、それらは何を意味するのでしょうか? この公理は、 iffが よりも大きく、よりも小さいことを示しています。公理のような提案された仕様は次のようになります。><Greaterxyyx

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

したがって、公理は次の種類の質問に答えます。

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

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

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

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

  • Greater:いつでもx > y、そしてy < x

  • Less_equal:いつでもx <= y、そして!(y < x)

  • Copy_equality: For xand yof type T: if x == y, コピー構築によって作成された同じ型の新しいオブジェクトT{x} == yと静止x == y(つまり、非破壊的)。

コンセプト

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

例として、次の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>;
}

まず、テンプレート タイプTを にするには、コンセプトOrderedの要件も満たしている必要があります。RegularこのRegular概念は、型が適切に動作するという非常に基本的な要件です。つまり、型を構築、破棄、コピー、および比較できます。

これらの要件に加えて、1 つの制約と 4 つの公理Orderedを満たす必要があります。T

  • 制約:Ordered型にはoperator<. これは静的にチェックされるため、存在する必要があります。
  • 公理: forxおよびyof type T:
    • x < y厳密な全順序付けを行います。
    • xが よりも大きい場合は よりも小さくy、その逆も同様です。yx
    • xが より小さいか等しい場合、yy未満ではなくx、その逆も同様です。
    • xが より大きいか等しい場合、yyより大きくなくx、その逆も同様です。

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

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

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

  • Regular型は、構築可能、破壊可能、コピー可能であり、比較できます。

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

  • Copyable型はコピー構築可能、破壊可能であり、xが と等しくyxがコピーされる場合、コピーも と等しいと比較されyます。

  • Iteratorvalue_type型には、型、referencedifference_type、およびが関連付けられている必要があり、iterator_categoryそれら自体が特定の概念を満たしている必要があります。また、サポートoperator++し、逆参照可能でなければなりません。

コンセプトへの道

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

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

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

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

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

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

于 2013-03-27T23:13:35.577 に答える
22

また、最近 (3 月 12 日) のコンセプト テレコン議事録のセクション 2.3 にある「コンセプト ライトについての「ライト」とは」と、同じ日にここに投稿された議論の記録を参照してください: http://isocpp.org/blog/2013/03 /new-paper-n3576-sg8-concepts-teleconference-minutes-2013-03-12-herb-sutter .

于 2013-03-28T23:03:34.167 に答える
4

私の2セント:

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

  2. コンセプトライトは、コンパイラによってサポートされている構文トリックを少し使って、美化された constexpr 関数を使用します。検索ルールに変更はありません。

  3. プログラマーは概念マップを作成する必要はありません。

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

于 2013-03-28T23:50:14.740 に答える