Showing posts with label cpp_CppCoreGuidelines. Show all posts
Showing posts with label cpp_CppCoreGuidelines. Show all posts

Feb 14, 2022

[C++][book review] Beautiful C++

Reference:
[Book] https://www.amazon.com/Beautiful-Core-Guidelines-Writing-Clean/dp/0137647840
[Cpp core guideline] https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#main



F.51: Where there is a choice, prefer default arguments over overloading

C.45: Don’t define a default constructor that only initializes data members; use in-class member initializers instead

C.131: Avoid trivial getters and setters

ES.10: Declare one name (only) per declaration

NR.2: Don’t insist to have only a single return-statement in a function

P.11: Encapsulate messy constructs, rather than spreading through the code

I.23: Keep the number of function arguments low

Do as little as possible, but no less
x64 ABI, there is a four-register fast-call calling convention by default.
A four-parameter function will execute slightly faster than a function taking a class by reference.

I.26: If you want a cross-compiler ABI, use a C-style subset

C.47: Define and initialize member variables in the order of member declaration

CP.3: Minimize explicit sharing of writable data

CP.22: Never call unknown code while holding a lock (e.g., a callback)
"Don’t communicate by sharing memory; share memory by communicating"

T.120: Use template metaprogramming only when you really need to

Meta-programming techniques, while useful, have been adopted into the lan- guage more explicitly.
consider using concept in C++20.

I.11: Never transfer ownership by a raw pointer (T*) or reference (T&)

Your default choice for holding objects with dynamic storage duration should be a std::unique_ ptr.
You should only use std::shared_ptr where reasoning about lifetime and ownership is impossibly hard, and even then, you should treat it as a sign of impending technical debt caused by a failure to observe the appropriate abstraction.

Use GSL:
http://github.com/Microsoft/GSL

I.3: Avoid singletons

C.90: Rely on constructors and assignment operators, not memset and memcpy

ES.50: Don’t cast away const

ES.5: Keep scopes small

CP.43: Minimize time spent in a critical section

E.28: Avoid error handling based on global state (e.g. errno)

You do not know how your calling code is going to respond to errors.
You cannot rely on your caller handling the error.

SF.7: Don’t write using namespace at global scope in a "header file"

F.21: To return multiple “out” values, prefer returning a struct or tuple

Enum.3: Prefer class enums over “plain” enums

ES.5: Keep scopes small

only declare auto-variables that is close to its use. (Golang)

Con.5: Use constexpr for values that can be computed at compile time

T.1: Use templates to raise the level of abstraction of code

T.10: Specify concepts for all template arguments (C++20)

P.4: Ideally, a program should be statically type safe

Problem areas:

  • unions - use variant (in C++17)
  • casts - minimize their use; templates can help
  • array decay - use span (from the GSL)
  • range errors - use span
  • narrowing conversions - minimize their use and use narrow or narrow_cast (from the GSL) where they are necessary
If you are doing any arithmetic, including comparison, use a signed type. If you are using an unsigned type to get an extra bit of representation, you are using the wrong type and you should go wider or recognize that you are performing a very risky optimization.


P.10: Prefer immutable data to mutable data

I.30: Encapsulate rule violations

ES.22: Don’t declare a variable until you have a value to initialize it with

Declaring at point of use improves readability of code, and not declaring state at all improves things even further. Reasoning about state requires a comprehensive memory, which is a diminishing asset as codebases expand.

Per.7: Design to enable optimization

E.6: Use RAII to prevent leaks

Nov 27, 2018

[C++][cppconf 2018] "Trivially Relocatable" Arthur O'Dwyer



Definition:
iff a move constructor and a destructor are non-trivial in pair,
the result is tantamount to 'memcpy', thus defined by Arthur as 'relocatable'.

e.g std::shared_ptr

Thus, in compiler, can't we just do a 'memcpy' instead of following
the language syntax doing a move construct + destruct?
Yes, we can!


Reference:
https://quuxplusone.github.io/blog/2018/07/18/announcing-trivially-relocatable/
https://www.youtube.com/watch?v=8u5Qi4FgTP8

assembly: call vs. callq
https://stackoverflow.com/a/46753525
quote:
It's just 'call'. Use Intel-syntax disassembly if you want to be able to look up instructions in the Intel/AMD manuals.

The q operand-size suffix does technically apply (it pushes a 64-bit return address and treats RIP as a 64-bit register), but there's no way to override it with instruction prefixes.
i.e. calll and callw aren't encodeable in 64-bit mode, so it's just annoying that some AT&T syntax tools show it as callq instead of call. This of course applies to retq as well.


Is this new?
nope :-)
In Lippman's Inside the C++ Object Model mentioned that inside the copy constructor
we could use system call memcpy to speed up the bit-wise copy; however, there's a gotcha, which is  object slice, which could accidentally copy the derived object's v-ptr.
In Arthur's proposal, we modify compiler(not run-time), implement the memcpy directly when
the type has Rule Of Zero trait.
C++ core quideline: C.20: If you can avoid defining default operations, do
C++ core guideline: C.67: A polymorphic class should suppress copying

Oct 4, 2015

[C++] Cpp Core Guidelines, excerpts that I might overlook.

https://github.com/isocpp/CppCoreGuidelines



array_view  // void copy(array_view<const T> r, array_view<T> r2); // copy r to r2
            // void copy_n(array_view<const T> p, array_view<T> q); // copy from p to q
string_view

owner<>
not_null<> // int length(not_null<const char*> p);
zstring  // Use zstring and czstring to represent a C-style, zero-terminated strings.

Expects  // Prefer Expects() for expressing preconditions
Ensures  // Post condition


----------------
[[lifetime(this)]]