C ++の完全な概念の提案とテンプレートの制約(たとえば、Dlangに表示される制約やC ++ 1yの新しいconcepts-liteの提案)の意味上の違いは何ですか?
テンプレートの制約ができないよりも、本格的なコンセプトは何ができるのですか?
C ++の完全な概念の提案とテンプレートの制約(たとえば、Dlangに表示される制約やC ++ 1yの新しいconcepts-liteの提案)の意味上の違いは何ですか?
テンプレートの制約ができないよりも、本格的なコンセプトは何ができるのですか?
回答:
次の情報は古くなっています。最新のConcepts Liteドラフトに従って更新する必要があります。
制約案のセクション3では、これについて妥当な範囲で説明しています。
コンセプトの提案は、制約(つまり、concepts-lite)を具体化してより短い時間スケールで実装でき、現在C ++ 14で少なくとも何かを目指していることを期待して、しばらくの間、後回しにされています。制約の提案は、後の概念の定義へのスムーズな移行として機能するように設計されています。制約は概念提案の一部であり、その定義に必要なビルディングブロックです。
ではC ++のためのコンセプトのライブラリの設計、サットンとStroustrup氏は次のような関係を考慮してください。
概念=制約+公理
それらの意味をすばやく要約するには:
したがって、公理(セマンティックプロパティ)を制約(構文プロパティ)に追加すると、概念が得られます。
concepts-liteの提案は最初の部分である制約のみをもたらしますが、これは本格的な概念に向けた重要かつ必要なステップです。
制約はすべて構文に関するものです。これらは、コンパイル時に型のプロパティを静的に識別する方法を提供するため、構文プロパティに基づいてテンプレート引数として使用される型を制限できます。制約に関する現在の提案では、それらは&&
およびのような論理接続詞を使用して命題計算のサブセットで表現され||
ます。
実際の制約を見てみましょう:
template <typename Cont>
requires Sortable<Cont>()
void sort(Cont& container);
ここでは、という関数テンプレートを定義していますsort
。新しい追加はrequire句です。require節は、この関数のテンプレート引数にいくつかの制約を与えます。特に、この制約は型が型でCont
なければならないことを示していSortable
ます。きちんとしたことは、次のように、より簡潔な形式で記述できることです。
template <Sortable Cont>
void sort(Cont& container);
Sortable
この関数で考慮されていないものを渡そうとすると、推定された型が型でT
はないことをすぐに伝える素敵なエラーが表示されSortable
ます。C ++ 11でこれを実行した場合、関数の内部からスローされた恐ろしいエラーが発生sort
し、誰にとっても意味がありません。
制約述語は、タイプ特性と非常に似ています。それらはいくつかのテンプレート引数タイプを取り、それに関するいくつかの情報を提供します。制約は、タイプに関する次の種類の質問に答えようとします。
ただし、制約は型の特性を置き換えるものではありません。代わりに、彼らは協力して働きます。一部のタイプ特性は、概念の観点から定義できるようになり、一部の概念はタイプ特性の観点から定義できます。
したがって、制約についての重要なことは、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>
制約があることを教えてくれますoperator==
タイプをとるT
とU
、それはあなたが何をその操作は教えてくれない手段。そのためには、公理がありEquivalence_relation
ます。この公理は、これらの2つのタイプのオブジェクトを比較するとことを言うoperator==
与えtrue
、これらのオブジェクトは等価です。これは冗長に見えるかもしれませんが、確かにそうではありません。operator==
代わりにのように動作するを簡単に定義できますoperator<
。あなたはそれをするのは悪いことですが、そうすることができます。
別の例はGreater
公理です。タイプの2つのオブジェクトT
を>
and <
演算子で比較できると言ってもいいのですが、それらはどういう意味ですか?Greater
公理は、IFFはと言う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
: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<
です。これは静的にチェックされるため、存在する必要があります。x
とy
タイプのT
:
x < y
厳密な合計順序を示します。x
よりも大きいy
、y
未満でありx
、そして逆もまた同様です。x
がより小さいか等しい場合、は未満y
でy
はなくx
、その逆も同様です。x
以上に等しくy
、y
より大きくないx
、そして逆もまた同様です。このように制約と公理を組み合わせると、概念がわかります。これらは、アルゴリズムで使用するための抽象型の構文要件と意味要件を定義します。アルゴリズムは現在、使用される型が特定の操作をサポートし、特定のセマンティクスを表現すると想定する必要があります。コンセプトがあれば、要件を確実に満たすことができます。
では、最新のコンセプト設計、コンパイラは概念のみの構文の要件はテンプレート引数によって満たされていることを確認します。公理はチェックされません。公理は静的に評価できない(または完全にチェックできないことが多い)セマンティクスを表すため、型の作成者は、その型が概念のすべての要件を満たしていることを明示的に述べる必要があります。これは以前の設計ではコンセプトマッピングとして知られていましたが、その後削除されました。
以下に概念の例をいくつか示します。
Regular
タイプは構成可能、破壊可能、コピー可能であり、比較することができます。
Ordered
型はをサポートしoperator<
、厳密な合計順序とその他の順序のセマンティクスを持っています。
Copyable
種類は破壊可能、構築可能にコピーされ、そして場合x
ISに等しい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にある「concepts 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は、私が正しく覚えているとしたら、コンセプトが多い提案では、テンプレートの実装を満たすために提供されるタイプが少なくない、または増えないタイプです。
concepts-liteは、コンパイラによってサポートされている少しの構文トリックを備えた栄光のあるconstexpr関数を使用しています。検索ルールに変更はありません。
プログラマーは概念マップを作成する必要はありません。
最後に、「制約の提案は、仕様やセマンティクスの使用に直接対処するものではありません。構文のチェックのみを目的としています。」つまり、公理は範囲内にありません(これまでのところ)。