mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2025-12-17 12:44:42 +03:00
Merge branch 'style-fix26' of https://github.com/tkruse/CppCoreGuidelines into tkruse-style-fix26
This commit is contained in:
@@ -371,7 +371,7 @@ The second version leaves the reader guessing and opens more possibilities for u
|
|||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
void do_something(vector<string>& v)
|
void f(vector<string>& v)
|
||||||
{
|
{
|
||||||
string val;
|
string val;
|
||||||
cin >> val;
|
cin >> val;
|
||||||
@@ -388,7 +388,7 @@ The second version leaves the reader guessing and opens more possibilities for u
|
|||||||
That loop is a restricted form of `std::find`.
|
That loop is a restricted form of `std::find`.
|
||||||
A much clearer expression of intent would be:
|
A much clearer expression of intent would be:
|
||||||
|
|
||||||
void do_something(vector<string>& v)
|
void f(vector<string>& v)
|
||||||
{
|
{
|
||||||
string val;
|
string val;
|
||||||
cin >> val;
|
cin >> val;
|
||||||
@@ -2315,7 +2315,7 @@ When copying is cheap, nothing beats the simplicity and safety of copying, and f
|
|||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
void f(const string& s); // OK: pass by reference to const; always cheap
|
void f1(const string& s); // OK: pass by reference to const; always cheap
|
||||||
|
|
||||||
void f2(string s); // bad: potentially expensive
|
void f2(string s); // bad: potentially expensive
|
||||||
|
|
||||||
@@ -4707,7 +4707,7 @@ If the state of a base class object must depend on the state of a derived part o
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class D : public B { /* "¦ */ }; // some derived class
|
class D : public B { /* ... */ }; // some derived class
|
||||||
|
|
||||||
shared_ptr<D> p = D::Create<D>(); // creating a D object
|
shared_ptr<D> p = D::Create<D>(); // creating a D object
|
||||||
|
|
||||||
@@ -5739,13 +5739,13 @@ Such as on an ABI (link) boundary.
|
|||||||
};
|
};
|
||||||
|
|
||||||
class D2 : public Device {
|
class D2 : public Device {
|
||||||
// ... differnt data ...
|
// ... different data ...
|
||||||
|
|
||||||
void write(span<const char> outbuf) override;
|
void write(span<const char> outbuf) override;
|
||||||
void read(span<char> inbuf) override;
|
void read(span<char> inbuf) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
A user can now use `D1`s and `D2`s interrchangeably through the interface provided by `Device`.
|
A user can now use `D1`s and `D2`s interchangeably through the interface provided by `Device`.
|
||||||
Furthermore, we can update `D1` and `D2` in a ways that are not binarily compatible with older versions as long as all access goes through `Device`.
|
Furthermore, we can update `D1` and `D2` in a ways that are not binarily compatible with older versions as long as all access goes through `Device`.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
@@ -6745,7 +6745,7 @@ Readability. Convention. Reusability. Support for generic code
|
|||||||
return os << /* class members here */;
|
return os << /* class members here */;
|
||||||
}
|
}
|
||||||
|
|
||||||
By itself, `cout_my_class` would be OK, but it is not usable/composabe with code that rely on the `<<` convention for output:
|
By itself, `cout_my_class` would be OK, but it is not usable/composable with code that rely on the `<<` convention for output:
|
||||||
|
|
||||||
My_class var { /* ... */ };
|
My_class var { /* ... */ };
|
||||||
// ...
|
// ...
|
||||||
@@ -7272,7 +7272,7 @@ The members of a scoped object are themselves scoped and the scoped object's con
|
|||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
The following example is inefficient (because it has unnecessary allocation and deallocation), vulnerable to exception throws and returns in the "¦ part (leading to leaks), and verbose:
|
The following example is inefficient (because it has unnecessary allocation and deallocation), vulnerable to exception throws and returns in the `...` part (leading to leaks), and verbose:
|
||||||
|
|
||||||
void f(int n)
|
void f(int n)
|
||||||
{
|
{
|
||||||
@@ -8445,7 +8445,7 @@ solution:
|
|||||||
j = f4();
|
j = f4();
|
||||||
}
|
}
|
||||||
|
|
||||||
Now the compiler cannot even simply detect a used-before-set. Further, we've introduced complexity in the state space for widget: which operations are valid on an `unint` widget and which are not?
|
Now the compiler cannot even simply detect a used-before-set. Further, we've introduced complexity in the state space for widget: which operations are valid on an `uninit` widget and which are not?
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
@@ -10869,7 +10869,7 @@ Let cleanup actions on the unwinding path be handled by [RAII](#Re-raii).
|
|||||||
|
|
||||||
This code is messy.
|
This code is messy.
|
||||||
There could be a leak from the naked pointer in the `try` block.
|
There could be a leak from the naked pointer in the `try` block.
|
||||||
Not all exceptiones are handled.
|
Not all exceptions are handled.
|
||||||
`deleting` an object that failed to construct is almost certainly a mistake.
|
`deleting` an object that failed to construct is almost certainly a mistake.
|
||||||
Better:
|
Better:
|
||||||
|
|
||||||
@@ -10916,8 +10916,8 @@ Even without exceptions, [RAII](#Re-raii) is usually the best and most systemati
|
|||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
Error handling using exceptions is the only complete and systematic way of handling non-local errors in C++.
|
Error handling using exceptions is the only complete and systematic way of handling non-local errors in C++.
|
||||||
In particular, non-intrusively signalling failure to construct an object requires an exception.
|
In particular, non-intrusively signaling failure to construct an object requires an exception.
|
||||||
Signalling errors in a way that cannot be ignored requires exceptions.
|
Signaling errors in a way that cannot be ignored requires exceptions.
|
||||||
If you can't use exceptions, simulate their use as best you can.
|
If you can't use exceptions, simulate their use as best you can.
|
||||||
|
|
||||||
A lot of fear of exceptions is misguided.
|
A lot of fear of exceptions is misguided.
|
||||||
@@ -10986,7 +10986,7 @@ In such cases, "crashing" is simply leaving error handling to the next level of
|
|||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
void do_something(int n)
|
void f(int n)
|
||||||
{
|
{
|
||||||
// ...
|
// ...
|
||||||
p = static_cast<X*>(malloc(n, X));
|
p = static_cast<X*>(malloc(n, X));
|
||||||
@@ -10996,7 +10996,7 @@ In such cases, "crashing" is simply leaving error handling to the next level of
|
|||||||
|
|
||||||
Most systems cannot handle memory exhaustion gracefully anyway. This is roughly equivalent to
|
Most systems cannot handle memory exhaustion gracefully anyway. This is roughly equivalent to
|
||||||
|
|
||||||
void do_something(Int n)
|
void f(Int n)
|
||||||
{
|
{
|
||||||
// ...
|
// ...
|
||||||
p = new X[n]; // throw if memory is exhausted (by default, terminate)
|
p = new X[n]; // throw if memory is exhausted (by default, terminate)
|
||||||
@@ -11093,7 +11093,7 @@ and to avoid confusion with other uses of `std::pair`.
|
|||||||
|
|
||||||
###### Example
|
###### Example
|
||||||
|
|
||||||
In general, you must clean up before an eror exit.
|
In general, you must clean up before an error exit.
|
||||||
This can be messy:
|
This can be messy:
|
||||||
|
|
||||||
std::pair<int, error_indicator> user()
|
std::pair<int, error_indicator> user()
|
||||||
@@ -11123,7 +11123,7 @@ This can be messy:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Simulating RAII can be non-trivial, especially in functions with multiple resources and multiple possible errors.
|
Simulating RAII can be non-trivial, especially in functions with multiple resources and multiple possible errors.
|
||||||
A not uncommon technique is to gather cleanup at the end of the function to avoid repetittion:
|
A not uncommon technique is to gather cleanup at the end of the function to avoid repetition:
|
||||||
|
|
||||||
std::pair<int, error_indicator> user()
|
std::pair<int, error_indicator> user()
|
||||||
{
|
{
|
||||||
@@ -11154,7 +11154,7 @@ A not uncommon technique is to gather cleanup at the end of the function to avoi
|
|||||||
}
|
}
|
||||||
|
|
||||||
The larger the function, the more tempting this technique becomes.
|
The larger the function, the more tempting this technique becomes.
|
||||||
Aso, the larger the program becomes the harder it is to apply an error-indicator-based error handling strategy systematically.
|
Also, the larger the program becomes the harder it is to apply an error-indicator-based error handling strategy systematically.
|
||||||
|
|
||||||
We [prefer exception-based error handling](#Re-throw) and recommend [keeping functions short](#Rf-single).
|
We [prefer exception-based error handling](#Re-throw) and recommend [keeping functions short](#Rf-single).
|
||||||
|
|
||||||
@@ -11179,7 +11179,7 @@ See also [Simulating RAII](#Re-no-throw-raii).
|
|||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
C-stye error handling is based on the global variable `errno`, so it is essentially impossible to avoid this style completely.
|
C-style error handling is based on the global variable `errno`, so it is essentially impossible to avoid this style completely.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
@@ -12040,9 +12040,9 @@ In general, passing function objects gives better performance than passing point
|
|||||||
auto y = find_if(v, [](double x) { return x > 7; }); // function object: carries the needed data
|
auto y = find_if(v, [](double x) { return x > 7; }); // function object: carries the needed data
|
||||||
auto z = find_if(v, Greater_than<double>(7)); // function object: carries the needed data
|
auto z = find_if(v, Greater_than<double>(7)); // function object: carries the needed data
|
||||||
|
|
||||||
You can, of course, gneralize those functions using `auto` or (when and where available) concepts. For example:
|
You can, of course, generalize those functions using `auto` or (when and where available) concepts. For example:
|
||||||
|
|
||||||
auto y1 = find_if(v, [](Ordered x) { return x > 7; }); // reruire an ordered type
|
auto y1 = find_if(v, [](Ordered x) { return x>7; }); // require an ordered type
|
||||||
auto z1 = find_if(v, [](auto x) { return x>7; }); // hope that the type has a >
|
auto z1 = find_if(v, [](auto x) { return x>7; }); // hope that the type has a >
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
@@ -12262,7 +12262,7 @@ Semiregular requires default constructible.
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace T0 {
|
namespace T0 {
|
||||||
bool operator==(int, Bad::S) { cout << "T0\n"; return true; } // compate to int
|
bool operator==(int, Bad::S) { cout << "T0\n"; return true; } // compare to int
|
||||||
|
|
||||||
void test()
|
void test()
|
||||||
{
|
{
|
||||||
@@ -15691,7 +15691,7 @@ Alternatively, we will decide that no change is needed and delete the entry.
|
|||||||
* How granular should namespaces be? All classes/functions designed to work together and released together (as defined in Sutter/Alexandrescu) or something narrower or wider?
|
* How granular should namespaces be? All classes/functions designed to work together and released together (as defined in Sutter/Alexandrescu) or something narrower or wider?
|
||||||
* Should there be inline namespaces (à la `std::literals::*_literals`)?
|
* Should there be inline namespaces (à la `std::literals::*_literals`)?
|
||||||
* Avoid implicit conversions
|
* Avoid implicit conversions
|
||||||
* Const member functions should be thread safe "¦ aka, but I don't really change the variable, just assign it a value the first time it’s called "¦ argh
|
* Const member functions should be thread safe ... aka, but I don't really change the variable, just assign it a value the first time it’s called ... argh
|
||||||
* Always initialize variables, use initialization lists for member variables.
|
* Always initialize variables, use initialization lists for member variables.
|
||||||
* Anyone writing a public interface which takes or returns `void*` should have their toes set on fire. That one has been a personal favorite of mine for a number of years. :)
|
* Anyone writing a public interface which takes or returns `void*` should have their toes set on fire. That one has been a personal favorite of mine for a number of years. :)
|
||||||
* Use `const`-ness wherever possible: member functions, variables and (yippee) `const_iterators`
|
* Use `const`-ness wherever possible: member functions, variables and (yippee) `const_iterators`
|
||||||
|
|||||||
Reference in New Issue
Block a user