mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2024-03-22 13:30:58 +08:00
Merge remote-tracking branch 'refs/remotes/origin/master'
This commit is contained in:
commit
cc284d260f
|
@ -1864,15 +1864,25 @@ It is usually best to avoid global (namespace scope) objects altogether.
|
||||||
|
|
||||||
Having many arguments opens opportunities for confusion. Passing lots of arguments is often costly compared to alternatives.
|
Having many arguments opens opportunities for confusion. Passing lots of arguments is often costly compared to alternatives.
|
||||||
|
|
||||||
|
##### Discussion
|
||||||
|
|
||||||
|
The two most common reasons why functions have too many parameters are:
|
||||||
|
|
||||||
|
1. *Missing an abstraction.* There is an abstraction missing, so that a compound value is being passed as individual elements instead of as a single object that enforces an invariant. This not only expands the parameter list, but it leads to errors because the component values are no longer protected by an enforced invariant.
|
||||||
|
|
||||||
|
2. *Violating "one function, one responsibility."* The function is trying to do more than one job and should probably be refactored.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
The standard-library `merge()` is at the limit of what we can comfortably handle
|
The standard-library `merge()` is at the limit of what we can comfortably handle:
|
||||||
|
|
||||||
template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
|
template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
|
||||||
OutputIterator merge(InputIterator1 first1, InputIterator1 last1,
|
OutputIterator merge(InputIterator1 first1, InputIterator1 last1,
|
||||||
InputIterator2 first2, InputIterator2 last2,
|
InputIterator2 first2, InputIterator2 last2,
|
||||||
OutputIterator result, Compare comp);
|
OutputIterator result, Compare comp);
|
||||||
|
|
||||||
|
Note that this is because of problem 1 above -- missing abstraction. Instead of passing a range (abstraction), STL passed iterator pairs (unencapsulated component values).
|
||||||
|
|
||||||
Here, we have four template arguments and six function arguments.
|
Here, we have four template arguments and six function arguments.
|
||||||
To simplify the most frequent and simplest uses, the comparison argument can be defaulted to `<`:
|
To simplify the most frequent and simplest uses, the comparison argument can be defaulted to `<`:
|
||||||
|
|
||||||
|
@ -1894,12 +1904,24 @@ Alternatively, we could use concepts (as defined by the ISO TS) to define the no
|
||||||
Mergeable{In1 In2, Out}
|
Mergeable{In1 In2, Out}
|
||||||
OutputIterator merge(In1 r1, In2 r2, Out result);
|
OutputIterator merge(In1 r1, In2 r2, Out result);
|
||||||
|
|
||||||
|
##### Example
|
||||||
|
|
||||||
|
The safety Profiles recommend replacing
|
||||||
|
|
||||||
|
void f(int* some_ints, int some_ints_length); // BAD: C style, unsafe
|
||||||
|
|
||||||
|
with
|
||||||
|
|
||||||
|
void f(gsl::span<int> some_ints); // GOOD: safe, bounds-checked
|
||||||
|
|
||||||
|
Here, using an abstraction has safety and robustness benefits, and naturally also reduces the number of parameters.
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
How many arguments are too many? Try to use less than Four arguments.
|
How many parameters are too many? Try to use fewer than four (4) parameters.
|
||||||
There are functions that are best expressed with four individual arguments, but not many.
|
There are functions that are best expressed with four individual parameters, but not many.
|
||||||
|
|
||||||
**Alternative**: Group arguments into meaningful objects and pass the objects (by value or by reference).
|
**Alternative**: Use better abstraction: Group arguments into meaningful objects and pass the objects (by value or by reference).
|
||||||
|
|
||||||
**Alternative**: Use default arguments or overloads to allow the most common forms of calls to be done with fewer arguments.
|
**Alternative**: Use default arguments or overloads to allow the most common forms of calls to be done with fewer arguments.
|
||||||
|
|
||||||
|
@ -4551,7 +4573,7 @@ If a destructor uses operations that may fail, it can catch exceptions and in so
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
(Simple) A destructor should be declared `noexcept`.
|
(Simple) A destructor should be declared `noexcept` if it could throw.
|
||||||
|
|
||||||
### <a name="Rc-dtor-noexcept"></a>C.37: Make destructors `noexcept`
|
### <a name="Rc-dtor-noexcept"></a>C.37: Make destructors `noexcept`
|
||||||
|
|
||||||
|
@ -4561,11 +4583,11 @@ If a destructor uses operations that may fail, it can catch exceptions and in so
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
A destructor (either user-defined or compiler-generated) is implicitly declared `noexcept` (independently of what code is in its body) if all of the members of its class have `noexcept` destructors.
|
A destructor (either user-defined or compiler-generated) is implicitly declared `noexcept` (independently of what code is in its body) if all of the members of its class have `noexcept` destructors. By explicitly marking destructors `noexcept`, an author guards against the destructor becoming implicitly `noexcept(false)` through the addition or modification of a class member.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
(Simple) A destructor should be declared `noexcept`.
|
(Simple) A destructor should be declared `noexcept` if it could throw.
|
||||||
|
|
||||||
## <a name="SS-ctor"></a>C.ctor: Constructors
|
## <a name="SS-ctor"></a>C.ctor: Constructors
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user