An overload set may have some members that do not directly access `private` data:
class Foobar {
void foo(int x) { /* manipulate private data */ }
void foo(double x) { foo(std::round(x)); }
// ...
private:
// ...
};
Similarly, a set of functions may be designed to be used in a chain:
x.scale(0.5).rotate(45).set_color(Color::red);
Typically, some but not all of such functions directly access `private` data.
##### Enforcement
Look for member function that do not touch data members directly.
* Look for non-`virtual` member functions that do not touch data members directly.
The snag is that many member functions that do not need to touch data members directly do.
* Ignore `virtual` functions.
* Ignore functions that are part of an overload set out of which at least one function accesses `private` members.
* Ignore functions returning `this`.
### <aname="Rc-helper"></a>C.5: Place helper functions in the same namespace as the class they support
@ -6565,11 +6595,17 @@ Flag any class that has non-`const` data members with different access levels.
##### Reason
Not all classes will necessarily support all interfaces, and not all callers will necessarily want to deal with all operations. Especially to break apart monolithic interfaces into "aspects" of behavior supported by a given derived class.
Not all classes will necessarily support all interfaces, and not all callers will necessarily want to deal with all operations.
Especially to break apart monolithic interfaces into "aspects" of behavior supported by a given derived class.
##### Example
???
class iostream : public istream, public ostream { // very simplified
// ...
};
`istream` provides the interface to input operations; `ostream` provides the interface to output operations.
`iostream` provides the union of the `istream` and `ostream` interfaces and the synchronization needed to allow both on a single stream.
##### Note
@ -6588,11 +6624,17 @@ Such interfaces are typically abstract classes.
##### Reason
??? Herb: Here's the second mention of implementation inheritance. I'm very skeptical, even of single implementation inheritance, never mind multiple implementation inheritance which just seems frightening -- I don't think that even policy-based design really needs to inherit from the policy types. Am I missing some good examples, or could we consider discouraging this as an anti-pattern?
Some forms of mixins have state and often operations on that state.
If the operations are virtual the use of inheritance is necessary, if not using inheritance can avoid boilerplate and forwarding.
##### Example
???
class iostream : public istream, public ostream { // very simplified
// ...
};
`istream` provides the interface to input operations (and some data); `ostream` provides the interface to output operations (and some data).
`iostream` provides the union of the `istream` and `ostream` interfaces and the synchronization needed to allow both on a single stream.
##### Note
@ -6600,7 +6642,7 @@ This a relatively rare use because implementation can often be organized into a
##### Enforcement
??? Herb: How about opposite enforcement: Flag any type that inherits from more than one non-empty base class?
???
### <aname="Rh-vbase"></a>C.137: Use `virtual` bases to avoid overly general base classes
@ -7388,7 +7430,7 @@ But heed the warning: [Avoid "naked" `union`s](#Ru-naked)
##### Example
// Shortstring optimization
// Short-string optimization
constexpr size_t buffer_size = 16; // Slightly larger than the size of a pointer
@ -11723,8 +11765,11 @@ this can be a security risk.
##### Enforcement
Some is possible, do at least something.
There are commercial and open-source tools that try to address this problem, but static tools often have many false positives and run-time tools often have a significant cost.
There are commercial and open-source tools that try to address this problem,
but be aware that solutions have costs and blind spots.
Static tools often have many false positives and run-time tools often have a significant cost.
We hope for better tools.
Using multiple tools can catch more problems than a single one.
Help the tools:
@ -11850,11 +11895,11 @@ Use a `mutex` for more complicated examples.
[(rare) proper uses of `volatile`](#Rconc-volatile2)
### <aname="Rconc-tols"></a>CP.9: Whenever feasible use tools to validate your concurrent code
### <aname="Rconc-tools"></a>CP.9: Whenever feasible use tools to validate your concurrent code
Experience shows that concurrent code is exceptionally hard to get right
and that compile-time checking, run-time checks, and testing are less effective at finding concurrency errors
than they areat finding errors in sequential code.
than they areat finding errors in sequential code.
Subtle concurrency errors can have dramatically bad effects, including memory corruption and deadlocks.