mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2025-12-17 12:44:42 +03:00
a few minor changes
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# <a name="main"></a>C++ Core Guidelines
|
# <a name="main"></a>C++ Core Guidelines
|
||||||
|
|
||||||
July 20, 2016
|
July 21, 2016
|
||||||
|
|
||||||
Editors:
|
Editors:
|
||||||
|
|
||||||
@@ -12940,6 +12940,8 @@ Concept definition rule summary:
|
|||||||
* [T.24: Use tag classes or traits to differentiate concepts that differ only in semantics](#Rt-tag)
|
* [T.24: Use tag classes or traits to differentiate concepts that differ only in semantics](#Rt-tag)
|
||||||
* [T.25: Avoid complementary constraints](#Rt-not)
|
* [T.25: Avoid complementary constraints](#Rt-not)
|
||||||
* [T.26: Prefer to define concepts in terms of use-patterns rather than simple syntax](#Rt-use)
|
* [T.26: Prefer to define concepts in terms of use-patterns rather than simple syntax](#Rt-use)
|
||||||
|
* [T.30: Use concept negation (`!C<T>`) sparingly to express a minor difference](#Rt-not)
|
||||||
|
* [T.31: Use concept disjunction (`C1<T> || C2<T>`) sparingly to express alternatives](#Rt-or)
|
||||||
* ???
|
* ???
|
||||||
|
|
||||||
Template interface rule summary:
|
Template interface rule summary:
|
||||||
@@ -12964,7 +12966,6 @@ Template definition rule summary:
|
|||||||
* [T.67: Use specialization to provide alternative implementations for irregular types](#Rt-specialization2)
|
* [T.67: Use specialization to provide alternative implementations for irregular types](#Rt-specialization2)
|
||||||
* [T.68: Use `{}` rather than `()` within templates to avoid ambiguities](#Rt-cast)
|
* [T.68: Use `{}` rather than `()` within templates to avoid ambiguities](#Rt-cast)
|
||||||
* [T.69: Inside a template, don't make an unqualified nonmember function call unless you intend it to be a customization point](#Rt-customization)
|
* [T.69: Inside a template, don't make an unqualified nonmember function call unless you intend it to be a customization point](#Rt-customization)
|
||||||
* [T.75: Wrap traits in concepts](#Rt-traits)
|
|
||||||
|
|
||||||
Template and hierarchy rule summary:
|
Template and hierarchy rule summary:
|
||||||
|
|
||||||
@@ -13000,7 +13001,7 @@ Other template rules summary:
|
|||||||
* [T.142: Use template variables to simplify notation](#Rt-var)
|
* [T.142: Use template variables to simplify notation](#Rt-var)
|
||||||
* [T.143: Don't write unintentionally nongeneric code](#Rt-nongeneric)
|
* [T.143: Don't write unintentionally nongeneric code](#Rt-nongeneric)
|
||||||
* [T.144: Don't specialize function templates](#Rt-specialize-function)
|
* [T.144: Don't specialize function templates](#Rt-specialize-function)
|
||||||
* [T.150: Check that a class matches a concept using static_assert](#Rt-check-class)
|
* [T.150: Check that a class matches a concept using `static_assert`](#Rt-check-class)
|
||||||
* [T.??: ????](#Rt-???)
|
* [T.??: ????](#Rt-???)
|
||||||
|
|
||||||
## <a name="SS-GP"></a>T.gp: Generic programming
|
## <a name="SS-GP"></a>T.gp: Generic programming
|
||||||
@@ -13179,7 +13180,8 @@ Static helps dynamic: Use static polymorphism to implement dynamically polymorph
|
|||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
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).)
|
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)).
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
@@ -13187,9 +13189,15 @@ In a class template, nonvirtual functions are only instantiated if they're used
|
|||||||
This can bloat code size, and may overconstrain a generic type by instantiating functionality that is never needed.
|
This can bloat code size, and may overconstrain a generic type by instantiating functionality that is never needed.
|
||||||
Avoid this, even though the standard-library facets made this mistake.
|
Avoid this, even though the standard-library facets made this mistake.
|
||||||
|
|
||||||
|
##### See also
|
||||||
|
|
||||||
|
* ref ???
|
||||||
|
* ref ???
|
||||||
|
* ref ???
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
* Flag a class template that declares new (non-inherited) virtual functions.
|
See the reference to more specific rules.
|
||||||
|
|
||||||
## <a name="SS-concepts"></a>T.concepts: Concept rules
|
## <a name="SS-concepts"></a>T.concepts: Concept rules
|
||||||
|
|
||||||
@@ -13611,14 +13619,15 @@ Otherwise they cannot be distinguished automatically by the compiler.
|
|||||||
template<typename I>
|
template<typename I>
|
||||||
concept bool Fwd_iter = Input_iter<I> && requires (I iter) { iter++; }
|
concept bool Fwd_iter = Input_iter<I> && requires (I iter) { iter++; }
|
||||||
|
|
||||||
The compiler can determine refinement based on the sets of required operations.
|
The compiler can determine refinement based on the sets of required operations (here, suffix `++`).
|
||||||
This decreases the burden on implementers of these types since
|
This decreases the burden on implementers of these types since
|
||||||
they do not need any special declarations to "hook into the concept".
|
they do not need any special declarations to "hook into the concept".
|
||||||
If two concepts have exactly the same requirements, they are logically equivalent (there is no refinement).
|
If two concepts have exactly the same requirements, they are logically equivalent (there is no refinement).
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
* 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).
|
* 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).
|
||||||
|
|
||||||
### <a name="Rt-tag"></a>T.24: Use tag classes or traits to differentiate concepts that differ only in semantics.
|
### <a name="Rt-tag"></a>T.24: Use tag classes or traits to differentiate concepts that differ only in semantics.
|
||||||
|
|
||||||
@@ -13707,6 +13716,18 @@ Complementary constraints are unfortunately common in `enable_if` code:
|
|||||||
f();
|
f();
|
||||||
|
|
||||||
|
|
||||||
|
##### Note
|
||||||
|
|
||||||
|
Complementary requirements on one requirements is sometimes (wrongly) considered manageable.
|
||||||
|
However, for two or more requirements the number of definitions needs can go up exponentially (2,4,9,16,...):
|
||||||
|
|
||||||
|
C1<T> && C2<T>
|
||||||
|
!C1<T> && C2<T>
|
||||||
|
C1<T> && !C2<T>
|
||||||
|
!C1<T> && !C2<T>
|
||||||
|
|
||||||
|
Now the opportunities for errors multiply.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
* Flag pairs of functions with `C<T>` and `!C<T>` constraints
|
* Flag pairs of functions with `C<T>` and `!C<T>` constraints
|
||||||
@@ -13731,8 +13752,12 @@ Obviously, it would be better and easier just to use the standard `EqualityCompa
|
|||||||
bool == { a==b }
|
bool == { a==b }
|
||||||
bool == { a!=b }
|
bool == { a!=b }
|
||||||
// axiom { !(a==b)==(a!=b) }
|
// axiom { !(a==b)==(a!=b) }
|
||||||
|
// axiom { a=b; => a==b } // => means "implies"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
as oposed to defining two meaningless concepts `has_equal` and `has_not_equal` just as helpers in the definition of `Equality`.
|
||||||
|
By "meaningless" we mean that we cannot specify the semantics of `has_equal` in isolation.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
???
|
||||||
@@ -13794,9 +13819,9 @@ Consider, a `sort` instrumented with (oversimplified) simple debug support:
|
|||||||
|
|
||||||
void sort(Sortable& s) // sort sequence s
|
void sort(Sortable& s) // sort sequence s
|
||||||
{
|
{
|
||||||
if (debug) cerr << "enter sort()\n";
|
if (debug) cerr << "enter sort( " << s << ")\n";
|
||||||
// ...
|
// ...
|
||||||
if (debug) cerr << "exit sort()\n";
|
if (debug) cerr << "exit sort( " << s << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
Should this be rewritten to:
|
Should this be rewritten to:
|
||||||
@@ -13805,9 +13830,9 @@ Should this be rewritten to:
|
|||||||
requires Streamable<S>
|
requires Streamable<S>
|
||||||
void sort(S& s) // sort sequence s
|
void sort(S& s) // sort sequence s
|
||||||
{
|
{
|
||||||
if (debug) cerr << "enter sort()\n";
|
if (debug) cerr << "enter sort( " << s << ")\n";
|
||||||
// ...
|
// ...
|
||||||
if (debug) cerr << "exit sort()\n";
|
if (debug) cerr << "exit sort( " << s << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
After all, there is nothing in `Sortable` that requires `iostream` support.
|
After all, there is nothing in `Sortable` that requires `iostream` support.
|
||||||
@@ -13827,6 +13852,8 @@ By not using concept checking for properties of a template argument that is not
|
|||||||
we delay checking until instantiation time.
|
we delay checking until instantiation time.
|
||||||
We consider this a worthwhile tradeoff.
|
We consider this a worthwhile tradeoff.
|
||||||
|
|
||||||
|
Note that using non-local, non-dependent names (such as `debug` and `cerr`) also introduce context dependencies that may lead to "mysterious" errors.
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
It can be hard to decide which properties of a type is essential and which are not.
|
It can be hard to decide which properties of a type is essential and which are not.
|
||||||
@@ -13839,7 +13866,10 @@ It can be hard to decide which properties of a type is essential and which are n
|
|||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
@@ -13854,11 +13884,32 @@ This saves the user of `Matrix` from having to know that its elements are stored
|
|||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void user(T& c)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
typename container_traits<T>::value_type x; // bad, verbose
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using Value_type = typename container_traits<T>::value_type;
|
using Value_type = typename container_traits<T>::value_type;
|
||||||
|
|
||||||
|
|
||||||
This saves the user of `Value_type` from having to know the technique used to implement `value_type`s.
|
This saves the user of `Value_type` from having to know the technique used to implement `value_type`s.
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void user2(T& c)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
Value_type<T> x;
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
##### Note
|
||||||
|
|
||||||
|
A simple, common use could be expressed: "Wrap traits!"
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
* Flag use of `typename` as a disambiguator outside `using` declarations.
|
* 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
|
|||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
In many cases you can provide a stable interface by not parameterizing a base; see [Rule](#Rt-abi).
|
In many cases you can provide a stable interface by not parameterizing a base;
|
||||||
|
see ["stable base"](#Rt-abi) and [OO and GP](#Rt-generic-oo)
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
@@ -14520,7 +14572,8 @@ The compiler handles that.
|
|||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
Improve stability of code. Avoids code bloat.
|
Improve stability of code.
|
||||||
|
Avoid code bloat.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
@@ -14829,7 +14882,8 @@ whether functions, lambdas, or operators.
|
|||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
* (hard) flag similar lambdas
|
||||||
|
* ???
|
||||||
|
|
||||||
### <a name="Rt-lambda"></a>T.141: Use an unnamed lambda if you need a simple function object in one place only
|
### <a name="Rt-lambda"></a>T.141: Use an unnamed lambda if you need a simple function object in one place only
|
||||||
|
|
||||||
@@ -14941,6 +14995,33 @@ You can't partially specialize a function template per language rules. You can f
|
|||||||
|
|
||||||
* Flag all specializations of a function template. Overload instead.
|
* Flag all specializations of a function template. Overload instead.
|
||||||
|
|
||||||
|
|
||||||
|
### <a name="Rt-check-class"></a>T.150: Check that a class matches a concept using `static_assert`
|
||||||
|
|
||||||
|
##### Reason
|
||||||
|
|
||||||
|
If you intend for a class to match a concept, verifying that early saves users pain.
|
||||||
|
|
||||||
|
###### Example
|
||||||
|
|
||||||
|
class X {
|
||||||
|
X() = delete;
|
||||||
|
X(const X&) = default;
|
||||||
|
X(X&&) = default;
|
||||||
|
X& operator=(const X&) = default;
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
|
||||||
|
Somewhere, possibly in an implementation file, let the compiler check the desired properties of `X`:
|
||||||
|
|
||||||
|
static_assert(Default_constructible<X>); // error: X has no default constructor
|
||||||
|
static_assert(Copyable<X>); // error: we forgot to define X's move constructor
|
||||||
|
|
||||||
|
|
||||||
|
###### Enforcement
|
||||||
|
|
||||||
|
Not feasible.
|
||||||
|
|
||||||
# <a name="S-cpl"></a>CPL: C-style programming
|
# <a name="S-cpl"></a>CPL: C-style programming
|
||||||
|
|
||||||
C and C++ are closely related languages.
|
C and C++ are closely related languages.
|
||||||
|
|||||||
Reference in New Issue
Block a user