Skip to content

Commit d155244

Browse files
a few minor changes
1 parent 1b026e5 commit d155244

File tree

1 file changed

+97
-16
lines changed

1 file changed

+97
-16
lines changed

CppCoreGuidelines.md

Lines changed: 97 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# <a name="main"></a>C++ Core Guidelines
22

3-
July 20, 2016
3+
July 21, 2016
44

55
Editors:
66

@@ -12940,6 +12940,8 @@ Concept definition rule summary:
1294012940
* [T.24: Use tag classes or traits to differentiate concepts that differ only in semantics](#Rt-tag)
1294112941
* [T.25: Avoid complementary constraints](#Rt-not)
1294212942
* [T.26: Prefer to define concepts in terms of use-patterns rather than simple syntax](#Rt-use)
12943+
* [T.30: Use concept negation (`!C<T>`) sparingly to express a minor difference](#Rt-not)
12944+
* [T.31: Use concept disjunction (`C1<T> || C2<T>`) sparingly to express alternatives](#Rt-or)
1294312945
* ???
1294412946

1294512947
Template interface rule summary:
@@ -12964,7 +12966,6 @@ Template definition rule summary:
1296412966
* [T.67: Use specialization to provide alternative implementations for irregular types](#Rt-specialization2)
1296512967
* [T.68: Use `{}` rather than `()` within templates to avoid ambiguities](#Rt-cast)
1296612968
* [T.69: Inside a template, don't make an unqualified nonmember function call unless you intend it to be a customization point](#Rt-customization)
12967-
* [T.75: Wrap traits in concepts](#Rt-traits)
1296812969

1296912970
Template and hierarchy rule summary:
1297012971

@@ -13000,7 +13001,7 @@ Other template rules summary:
1300013001
* [T.142: Use template variables to simplify notation](#Rt-var)
1300113002
* [T.143: Don't write unintentionally nongeneric code](#Rt-nongeneric)
1300213003
* [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)
1300413005
* [T.??: ????](#Rt-???)
1300513006

1300613007
## <a name="SS-GP"></a>T.gp: Generic programming
@@ -13179,17 +13180,24 @@ Static helps dynamic: Use static polymorphism to implement dynamically polymorph
1317913180

1318013181
##### Example
1318113182

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)).
1318313185

1318413186
##### Note
1318513187

1318613188
In a class template, nonvirtual functions are only instantiated if they're used -- but virtual functions are instantiated every time.
1318713189
This can bloat code size, and may overconstrain a generic type by instantiating functionality that is never needed.
1318813190
Avoid this, even though the standard-library facets made this mistake.
1318913191

13192+
##### See also
13193+
13194+
* ref ???
13195+
* ref ???
13196+
* ref ???
13197+
1319013198
##### Enforcement
1319113199

13192-
* Flag a class template that declares new (non-inherited) virtual functions.
13200+
See the reference to more specific rules.
1319313201

1319413202
## <a name="SS-concepts"></a>T.concepts: Concept rules
1319513203

@@ -13611,14 +13619,15 @@ Otherwise they cannot be distinguished automatically by the compiler.
1361113619
template<typename I>
1361213620
concept bool Fwd_iter = Input_iter<I> && requires (I iter) { iter++; }
1361313621

13614-
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 `++`).
1361513623
This decreases the burden on implementers of these types since
1361613624
they do not need any special declarations to "hook into the concept".
1361713625
If two concepts have exactly the same requirements, they are logically equivalent (there is no refinement).
1361813626

1361913627
##### Enforcement
1362013628

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).
1362213631

1362313632
### <a name="Rt-tag"></a>T.24: Use tag classes or traits to differentiate concepts that differ only in semantics.
1362413633

@@ -13707,6 +13716,18 @@ Complementary constraints are unfortunately common in `enable_if` code:
1370713716
f();
1370813717

1370913718

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+
1371013731
##### Enforcement
1371113732

1371213733
* 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:
1372513746
template<typename T> concept Equality = has_equal<T> && has_not_equal<T>;
1372613747

1372713748
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:
1372913750

1373013751
template<typename T> concept Equality = requires(T a, T b) {
1373113752
bool == { a==b }
1373213753
bool == { a!=b }
1373313754
// axiom { !(a==b)==(a!=b) }
13755+
// axiom { a=b; => a==b } // => means "implies"
1373413756
}
1373513757

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+
1373613761
##### Enforcement
1373713762

1373813763
???
@@ -13794,9 +13819,9 @@ Consider, a `sort` instrumented with (oversimplified) simple debug support:
1379413819

1379513820
void sort(Sortable& s) // sort sequence s
1379613821
{
13797-
if (debug) cerr << "enter sort()\n";
13822+
if (debug) cerr << "enter sort( " << s << ")\n";
1379813823
// ...
13799-
if (debug) cerr << "exit sort()\n";
13824+
if (debug) cerr << "exit sort( " << s << ")\n";
1380013825
}
1380113826

1380213827
Should this be rewritten to:
@@ -13805,9 +13830,9 @@ Should this be rewritten to:
1380513830
requires Streamable<S>
1380613831
void sort(S& s) // sort sequence s
1380713832
{
13808-
if (debug) cerr << "enter sort()\n";
13833+
if (debug) cerr << "enter sort( " << s << ")\n";
1380913834
// ...
13810-
if (debug) cerr << "exit sort()\n";
13835+
if (debug) cerr << "exit sort( " << s << ")\n";
1381113836
}
1381213837

1381313838
After all, there is nothing in `Sortable` that requires `iostream` support.
@@ -13826,6 +13851,8 @@ we may get a late compile-time error.
1382613851
By not using concept checking for properties of a template argument that is not considered essential,
1382713852
we delay checking until instantiation time.
1382813853
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.
1382913856

1383013857
##### Note
1383113858

@@ -13839,7 +13866,10 @@ It can be hard to decide which properties of a type is essential and which are n
1383913866

1384013867
##### Reason
1384113868

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.
1384313873

1384413874
##### Example
1384513875

@@ -13854,11 +13884,32 @@ This saves the user of `Matrix` from having to know that its elements are stored
1385413884

1385513885
##### Example
1385613886

13887+
template<typename T>
13888+
void user(T& c)
13889+
{
13890+
// ...
13891+
typename container_traits<T>::value_type x; // bad, verbose
13892+
// ...
13893+
}
13894+
1385713895
template<typename T>
1385813896
using Value_type = typename container_traits<T>::value_type;
1385913897

13898+
1386013899
This saves the user of `Value_type` from having to know the technique used to implement `value_type`s.
1386113900

13901+
template<typename T>
13902+
void user2(T& c)
13903+
{
13904+
// ...
13905+
Value_type<T> x;
13906+
// ...
13907+
}
13908+
13909+
##### Note
13910+
13911+
A simple, common use could be expressed: "Wrap traits!"
13912+
1386213913
##### Enforcement
1386313914

1386413915
* Flag use of `typename` as a disambiguator outside `using` declarations.
@@ -14419,7 +14470,8 @@ Imagine what this would do to a class hierarchy with dozens of member functions
1441914470

1442014471
##### Note
1442114472

14422-
In many cases you can provide a stable interface by not parameterizing a base; see [Rule](#Rt-abi).
14473+
In many cases you can provide a stable interface by not parameterizing a base;
14474+
see ["stable base"](#Rt-abi) and [OO and GP](#Rt-generic-oo)
1442314475

1442414476
##### Enforcement
1442514477

@@ -14520,7 +14572,8 @@ The compiler handles that.
1452014572

1452114573
##### Reason
1452214574

14523-
Improve stability of code. Avoids code bloat.
14575+
Improve stability of code.
14576+
Avoid code bloat.
1452414577

1452514578
##### Example
1452614579

@@ -14829,7 +14882,8 @@ whether functions, lambdas, or operators.
1482914882

1483014883
##### Enforcement
1483114884

14832-
???
14885+
* (hard) flag similar lambdas
14886+
* ???
1483314887

1483414888
### <a name="Rt-lambda"></a>T.141: Use an unnamed lambda if you need a simple function object in one place only
1483514889

@@ -14941,6 +14995,33 @@ You can't partially specialize a function template per language rules. You can f
1494114995

1494214996
* Flag all specializations of a function template. Overload instead.
1494314997

14998+
14999+
### <a name="Rt-check-class"></a>T.150: Check that a class matches a concept using `static_assert`
15000+
15001+
##### Reason
15002+
15003+
If you intend for a class to match a concept, verifying that early saves users pain.
15004+
15005+
###### Example
15006+
15007+
class X {
15008+
X() = delete;
15009+
X(const X&) = default;
15010+
X(X&&) = default;
15011+
X& operator=(const X&) = default;
15012+
// ...
15013+
};
15014+
15015+
Somewhere, possibly in an implementation file, let the compiler check the desired properties of `X`:
15016+
15017+
static_assert(Default_constructible<X>); // error: X has no default constructor
15018+
static_assert(Copyable<X>); // error: we forgot to define X's move constructor
15019+
15020+
15021+
###### Enforcement
15022+
15023+
Not feasible.
15024+
1494415025
# <a name="S-cpl"></a>CPL: C-style programming
1494515026

1494615027
C and C++ are closely related languages.

0 commit comments

Comments
 (0)