C++の完全な概念の提案とテンプレートの制約(たとえば、Dlangまたは C++ 1yの新しいconcept-liteの提案 )に見られる制約のセマンティックな違いを知りたいです。
テンプレートの制約ではできない以上のことができる本格的なコンセプトは何ですか?
次の情報は古くなっています。最新のConcepts Liteドラフトに従って更新する必要があります。
制約の提案 のセクション3は、これを妥当な深さでカバーしています。
概念の提案 制約(概念-lite)がより短い時間スケールで肉付けされ、実装され、現在少なくとも何かを目指していることを期待して、しばらくの間バックバーナーに置かれましたC++ 14で。制約の提案は、後の概念の定義へのスムーズな移行として機能するように設計されています。制約はの一部概念の提案であり、その定義に必要な構成要素です。
C++のコンセプトライブラリの設計 では、SuttonとStroustrupは次の関係を考慮します。
概念=制約+公理
それらの意味をすばやく要約するには:
そのため、制約(構文プロパティ)に公理(意味プロパティ)を追加すると、概念が得られます。
コンセプトライトの提案は、最初の部分である制約のみをもたらしますが、これは本格的なコンセプトに向けた重要かつ必要なステップです。
制約はすべてsyntaxについてです。コンパイル時に型のプロパティを静的に識別する方法を提供するため、構文のプロパティに基づいてテンプレート引数として使用される型を制限できます。制約の現在の提案では、それらは&&
や||
のような論理接続詞を使用した命題計算のサブセットで表現されています。
実際の制約を見てみましょう。
template <typename Cont>
requires Sortable<Cont>()
void sort(Cont& container);
ここでは、sort
という関数テンプレートを定義しています。新しい追加はrequires句です。 require節は、この関数のテンプレート引数に対していくつかの制約を与えます。特に、この制約は、タイプCont
がSortable
タイプでなければならないことを示しています。すてきなことは、より簡潔な形式で次のように記述できることです。
template <Sortable Cont>
void sort(Cont& container);
Sortable
と見なされないものをこの関数に渡そうとすると、T
に対して推定される型がSortable
タイプ。 C++ 11でこれを行っていた場合、inside誰にも意味のないsort
関数からいくつかの恐ろしいエラーがスローされたでしょう。
制約述語は型特性に非常に似ています。彼らはいくつかのテンプレート引数タイプを取り、あなたにそれに関するいくつかの情報を与えます。制約は、タイプに関する次の種類の質問に答えようとします。
ただし、制約は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つのオブジェクトを>
および<
演算子と比較できると言ってもいいですが、それらは何ですかmean? Greater
公理は、x
がy
より大きい場合、y
がx
より小さい場合に限ります。公理などの提案された仕様は次のようになります。
template<typename T>
axiom Greater(T x, T y) {
(x>y) == (y<x);
}
したがって、公理は次のタイプの質問に答えます。
つまり、それらは完全に型のセマンティクスとそれらの型の操作に関係しています。これらを静的にチェックすることはできません。これをチェックする必要がある場合、型は何らかの方法でこれらのセマンティクスに従うことを宣言する必要があります。
公理の一般的な例を次に示します。
Equivalence_relation
:2つのオブジェクトが==
を比較する場合、それらは同等です。
Greater
:x > y
のたびに、y < x
。
Less_equal
:x <= y
のときはいつでも、!(y < x)
。
Copy_equality
:タイプx
のy
および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>;
}
最初に、テンプレートタイプT
をOrdered
にするには、Regular
コンセプトの要件も満たしている必要があります。 Regular
コンセプトは、型が適切に動作するための非常に基本的な要件です-構築、破棄、コピー、および比較が可能です。
これらの要件に加えて、Ordered
はT
が1つの制約と4つの公理を満たすことを要求します。
Ordered
型にはoperator<
が必要です。これは静的にチェックされるため、mustが存在します。x
:のy
およびT
の場合x < y
は、厳密な合計順序付けを提供します。x
がy
より大きい場合、y
はx
より小さい、またはその逆です。x
がy
以下である場合、y
はx
以上であり、その逆も同様です。x
がy
以上の場合、y
はx
以下であり、その逆も同様です。このように制約と公理を組み合わせると、概念が得られます。これらは、アルゴリズムで使用する抽象型の構文要件および意味要件を定義します。アルゴリズムは現在、使用されているタイプが特定の操作をサポートし、特定のセマンティクスを表現すると想定する必要があります。コンセプトにより、要件が満たされていることを確認できます。
最新の概念設計 では、コンパイラは、テンプレート引数によって概念の構文要件が満たされていることのみをチェックします。公理は未チェックのままです。公理は静的に評価できない(または完全にチェックできないことが多い)セマンティクスを示すため、型の作成者は、その型が概念のすべての要件を満たしていることを明示的に述べる必要があります。これは、以前の設計ではコンセプトマッピングとして知られていましたが、その後削除されました。
概念の例を次に示します。
Regular
型は、構築可能、破壊可能、コピー可能、および比較可能です。
Ordered
型はoperator<
をサポートし、厳密な合計順序付けおよびその他の順序付けセマンティクスを備えています。
Copyable
型はコピー可能、破壊可能です。x
がy
と等しく、x
がコピーされる場合、コピーもy
。
Iterator
タイプには、関連するタイプvalue_type
、reference
、difference_type
、およびiterator_category
が必要です。これらは、特定の概念を満たす必要があります。また、operator++
をサポートし、逆参照可能でなければなりません。
制約は、C++の完全な概念機能に向けた最初のステップです。型の静的に強制可能な要件を提供するため、非常に重要なステップであり、よりクリーンなテンプレート関数とクラスを作成できます。これで、std::enable_if
とそのメタプログラミングの友人の困難とさのいくつかを回避できます。
ただし、制約の提案ではできないことがいくつかあります。
概念定義言語は提供しません。
制約は概念マップではありません。ユーザーは、特定の制約を満たしているとタイプを明確に注釈する必要はありません。これらは、単純なコンパイル時言語機能を使用して静的にチェックされます。
テンプレートの実装は、テンプレート引数の制約によって制約されません。つまり、関数テンプレートが、実行すべきではない制約型のオブジェクトを使用して何かを行う場合、コンパイラーはそれを診断する方法がありません。完全な機能を備えた概念の提案により、これが可能になります。
制約の提案は、その上に完全な概念の提案を導入できるように特別に設計されています。運が良ければ、その移行はかなりスムーズに行われるはずです。コンセプトグループは、C++ 14(またはその後まもなくテクニカルレポート)に制約を導入することを検討していますが、C++ 17の前後に完全なコンセプトが出現し始める可能性があります。
また、同じ日に投稿された最近の(3月12日)Conceptsテレコン議事録とディスカッションの記録のセクション2.3の「概念liteについての「ライト」とは」も参照してください。 http://isocpp.org/blog/2013/03/new-paper-n3576-sg8-concepts-teleconference-minutes-2013-03-12-herb-sutter 。
私の2セント:
Concepts-Liteの提案は、テンプレートの「型チェック」を行うことを意図したものではありません実装。つまり、Concepts-liteは、テンプレートのインスタンス化サイトで(概念的に)インターフェイスの互換性を確保します。論文からの引用:「concepts liteは、テンプレート引数を制約する述語の使用を可能にするC++の拡張機能です」。以上です。テンプレート本体が述部に対して(単独で)チェックされるとは言いません。それはおそらく、concepts-liteについて話しているときにarchtypesのファーストクラスの概念がないことを意味します。私が正しく覚えていれば、概念の中で、archtypesは、テンプレートのimplementationを満たすために、それ以上でもそれ以上でもないタイプです。
concepts-Liteは、コンパイラーがサポートする少しの構文トリックを使用して、洗練されたconstexpr関数を使用します。ルックアップルールに変更はありません。
プログラマーは概念マップを書く必要はありません。
最後に、「制約の提案は、セマンティクスの仕様または使用に直接対処するものではありません。構文のチェックのみを対象としています。」これは、公理が範囲内にないことを意味します(これまで)。