You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* [T.144: Don't specialize function templates](#Rt-specialize-function)
13003
-
* [T.150: Check that a class matches a concept using static_assert](#Rt-check-class)
13004
+
* [T.150: Check that a class matches a concept using `static_assert`](#Rt-check-class)
13004
13005
* [T.??: ????](#Rt-???)
13005
13006
13006
13007
## <a name="SS-GP"></a>T.gp: Generic programming
@@ -13179,17 +13180,24 @@ Static helps dynamic: Use static polymorphism to implement dynamically polymorph
13179
13180
13180
13181
##### Example
13181
13182
13182
-
Dynamic helps static: Offer a generic, comfortable, statically bound interface, but internally dispatch dynamically, so you offer a uniform object layout. Examples include type erasure as with `std::shared_ptr`'s deleter. (But [don't overuse type erasure](#Rt-erasure).)
13183
+
Dynamic helps static: Offer a generic, comfortable, statically bound interface, but internally dispatch dynamically, so you offer a uniform object layout.
13184
+
Examples include type erasure as with `std::shared_ptr`'s deleter (but [don't overuse type erasure](#Rt-erasure)).
13183
13185
13184
13186
##### Note
13185
13187
13186
13188
In a class template, nonvirtual functions are only instantiated if they're used -- but virtual functions are instantiated every time.
13187
13189
This can bloat code size, and may overconstrain a generic type by instantiating functionality that is never needed.
13188
13190
Avoid this, even though the standard-library facets made this mistake.
13189
13191
13192
+
##### See also
13193
+
13194
+
* ref ???
13195
+
* ref ???
13196
+
* ref ???
13197
+
13190
13198
##### Enforcement
13191
13199
13192
-
* Flag a class template that declares new (non-inherited) virtual functions.
The compiler can determine refinement based on the sets of required operations.
13622
+
The compiler can determine refinement based on the sets of required operations (here, suffix `++`).
13615
13623
This decreases the burden on implementers of these types since
13616
13624
they do not need any special declarations to "hook into the concept".
13617
13625
If two concepts have exactly the same requirements, they are logically equivalent (there is no refinement).
13618
13626
13619
13627
##### Enforcement
13620
13628
13621
-
* Flag a concept that has exactly the same requirements as another already-seen concept (neither is more refined). To disambiguate them, see [T.24](#Rt-tag).
13629
+
* Flag a concept that has exactly the same requirements as another already-seen concept (neither is more refined).
13630
+
To disambiguate them, see [T.24](#Rt-tag).
13622
13631
13623
13632
### <a name="Rt-tag"></a>T.24: Use tag classes or traits to differentiate concepts that differ only in semantics.
13624
13633
@@ -13707,6 +13716,18 @@ Complementary constraints are unfortunately common in `enable_if` code:
13707
13716
f();
13708
13717
13709
13718
13719
+
##### Note
13720
+
13721
+
Complementary requirements on one requirements is sometimes (wrongly) considered manageable.
13722
+
However, for two or more requirements the number of definitions needs can go up exponentially (2,4,9,16,...):
13723
+
13724
+
C1<T> && C2<T>
13725
+
!C1<T> && C2<T>
13726
+
C1<T> && !C2<T>
13727
+
!C1<T> && !C2<T>
13728
+
13729
+
Now the opportunities for errors multiply.
13730
+
13710
13731
##### Enforcement
13711
13732
13712
13733
* Flag pairs of functions with `C<T>` and `!C<T>` constraints
@@ -13725,14 +13746,18 @@ You might be tempted to define a concept `Equality` like this:
Obviously, it would be better and easier just to use the standard `EqualityComparable`,
13728
-
but - just as an example - if you had to define such a concept, prefer:
13749
+
but - just as an example - if you had to define such a concept, prefer:
13729
13750
13730
13751
template<typename T> concept Equality = requires(T a, T b) {
13731
13752
bool == { a==b }
13732
13753
bool == { a!=b }
13733
13754
// axiom { !(a==b)==(a!=b) }
13755
+
// axiom { a=b; => a==b } // => means "implies"
13734
13756
}
13735
13757
13758
+
as oposed to defining two meaningless concepts `has_equal` and `has_not_equal` just as helpers in the definition of `Equality`.
13759
+
By "meaningless" we mean that we cannot specify the semantics of `has_equal` in isolation.
13760
+
13736
13761
##### Enforcement
13737
13762
13738
13763
???
@@ -13794,9 +13819,9 @@ Consider, a `sort` instrumented with (oversimplified) simple debug support:
13794
13819
13795
13820
void sort(Sortable& s) // sort sequence s
13796
13821
{
13797
-
if (debug) cerr << "enter sort()\n";
13822
+
if (debug) cerr << "enter sort( " << s << ")\n";
13798
13823
// ...
13799
-
if (debug) cerr << "exit sort()\n";
13824
+
if (debug) cerr << "exit sort( " << s << ")\n";
13800
13825
}
13801
13826
13802
13827
Should this be rewritten to:
@@ -13805,9 +13830,9 @@ Should this be rewritten to:
13805
13830
requires Streamable<S>
13806
13831
void sort(S& s) // sort sequence s
13807
13832
{
13808
-
if (debug) cerr << "enter sort()\n";
13833
+
if (debug) cerr << "enter sort( " << s << ")\n";
13809
13834
// ...
13810
-
if (debug) cerr << "exit sort()\n";
13835
+
if (debug) cerr << "exit sort( " << s << ")\n";
13811
13836
}
13812
13837
13813
13838
After all, there is nothing in `Sortable` that requires `iostream` support.
@@ -13826,6 +13851,8 @@ we may get a late compile-time error.
13826
13851
By not using concept checking for properties of a template argument that is not considered essential,
13827
13852
we delay checking until instantiation time.
13828
13853
We consider this a worthwhile tradeoff.
13854
+
13855
+
Note that using non-local, non-dependent names (such as `debug` and `cerr`) also introduce context dependencies that may lead to "mysterious" errors.
13829
13856
13830
13857
##### Note
13831
13858
@@ -13839,7 +13866,10 @@ It can be hard to decide which properties of a type is essential and which are n
13839
13866
13840
13867
##### Reason
13841
13868
13842
-
Improved readability. Implementation hiding. Note that template aliases replace many uses of traits to compute a type. They can also be used to wrap a trait.
13869
+
Improved readability.
13870
+
Implementation hiding.
13871
+
Note that template aliases replace many uses of traits to compute a type.
13872
+
They can also be used to wrap a trait.
13843
13873
13844
13874
##### Example
13845
13875
@@ -13854,11 +13884,32 @@ This saves the user of `Matrix` from having to know that its elements are stored
0 commit comments