diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index 7157325..733699e 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -2,6 +2,7 @@ February 11, 2017 + Editors: * [Bjarne Stroustrup](http://www.stroustrup.com) @@ -6690,11 +6691,49 @@ This a relatively rare use because implementation can often be organized into a ##### Reason -??? +Without a using declaration, member functions in the derived class hide the entire inherited overload sets. -##### Example +##### Example, bad - ??? + #include + class B { + public: + virtual int f(int i) { std::cout << "f(int): "; return i; } + virtual double f(double d) { std::cout << "f(double): "; return d; } + }; + class D: public B { + public: + int f(int i) override { std::cout << "f(int): "; return i+1; } + }; + int main() + { + D d; + std::cout << d.f(2) << '\n'; // prints "f(int): 3" + std::cout << d.f(2.3) << '\n'; // prints "f(int): 3" + } + +##### Example, good + + class D: public B { + public: + int f(int i) override { std::cout << "f(int): "; return i+1; } + using B::f; // exposes f(double) + }; + +##### Note + +This issue affects both virtual and non-virtual member functions + +For variadic bases, C++17 introduced a variadic form of the using-declaration, + + template + struct Overloader : Ts... { + using Ts::operator()...; // exposes operator() from every base + }; + +##### Enforcement + +Diagnose name hiding ### C.139: Use `final` sparingly @@ -7455,9 +7494,9 @@ But heed the warning: [Avoid "naked" `union`s](#Ru-naked) ##### Example // Short-string optimization - + constexpr size_t buffer_size = 16; // Slightly larger than the size of a pointer - + class Immutable_string { public: Immutable_string(const char* str) : @@ -7470,18 +7509,18 @@ But heed the warning: [Avoid "naked" `union`s](#Ru-naked) strcpy_s(string_ptr, size + 1, str); } } - + ~Immutable_string() { if (size >= buffer_size) delete string_ptr; } - + const char* get_str() const { return (size < buffer_size) ? string_buffer : string_ptr; } - + private: // If the string is short enough, we store the string itself // instead of a pointer to the string. @@ -7489,7 +7528,7 @@ But heed the warning: [Avoid "naked" `union`s](#Ru-naked) char* string_ptr; char string_buffer[buffer_size]; }; - + const size_t size; }; @@ -11795,12 +11834,12 @@ Static tools often have many false positives and run-time tools often have a sig We hope for better tools. Using multiple tools can catch more problems than a single one. -Help the tools: +There are other ways you can mitigate the chance of data races: -* less global data -* fewer `static` variables -* more use of stack memory (and don't pass pointers around too much) -* more immutable data (literals, `constexpr`, and `const`) +* Avoid global data +* Avoid `static` variables +* More use of value types on the stack (and don't pass pointers around too much) +* More use of immutable data (literals, `constexpr`, and `const`) ### CP.3: Minimize explicit sharing of writable data @@ -12432,7 +12471,8 @@ Thread creation is expensive. // process } - void master(istream& is) + void + (istream& is) { for (Message m; is >> m; ) run_list.push_back(new thread(worker, m)); @@ -12841,7 +12881,7 @@ Example with thread-safe static local variables of C++11. static My_class my_object; // Constructor called only once // ... } - + class My_class { public: @@ -12864,7 +12904,7 @@ Double-checked locking is easy to mess up. If you really need to write your own ##### Example, bad -Even if the following example works correctly on most hardware platforms, it is not guaranteed to work by the C++ standard. The x_init.load(memory_order_relaxed) call may see a value from outside of the lock guard. +Even if the following example works correctly on most hardware platforms, it is not guaranteed to work by the C++ standard. The x_init.load(memory_order_relaxed) call may see a value from outside of the lock guard. atomic x_init; @@ -12881,12 +12921,12 @@ Even if the following example works correctly on most hardware platforms, it is One of the conventional patterns is below. std::atomic state; - + // If state == SOME_ACTION_NEEDED maybe an action is needed, maybe not, we need to // check again in a lock. However, if state != SOME_ACTION_NEEDED, then we can be // sure that an action is not needed. This is the basic assumption of double-checked // locking. - + if (state == SOME_ACTION_NEEDED) { std::lock_guard lock(mutex); diff --git a/scripts/hunspell/isocpp.dic b/scripts/hunspell/isocpp.dic index 969393c..d4ae653 100644 --- a/scripts/hunspell/isocpp.dic +++ b/scripts/hunspell/isocpp.dic @@ -1,7 +1,9 @@ ' 0xFF0000 0b0101'0101 +10x '14 +20x 2D 2K 2ndEdition @@ -69,6 +71,7 @@ CComPtr cerr chrono cin +Clang's class' clib Cline99 @@ -492,6 +495,7 @@ toolchains TotallyOrdered TP tradeoff +TSAN TSs tt typeid