C Plus Plus
- C++ Basics ¶
- C++ Advance ¶
- C++ STL ¶
- C++ Design ¶
- C++ Core Guideline Tips ¶
- Guideline Support Library (gsl) ¶
- Unit Test ¶
- Building System and Generators ¶
C++ Basics ¶
Compiler Generated Functions ¶
- [1]. Default constructor (generated only if no other constructor declared by users, e.g. 1, 2, 4)
- [2]. Copy constructor (generated only if no 4 and 5 declared)
- [3]. Copy assignment (generated only if no 4 and 5 declared)
- [4]. Move constructor (generated only if no 2, 3, 5, 6 declared)
- [5]. Move assignment (generated only if no 2, 3, 4, 6 declared)
- [6]. Destructor (generated only if no virtual destructor is explicitly declared)
Note
: Rule 0 or Rule 5. If you need define any one of the others except constructor, then define all of them.
compiler_generated_functions.cc
User Defined Literals ¶
- Literals are constants
-
4 types of literals: integer 1, floating point 0.1, character 'x', string "abc".
- type suffix: 1024u -> unsigned int
user_literals.cc
C++ Advance ¶
Parameter Pack and Fold Expression ¶
-
Parameter Pack
-
In a template-parameter-list (template
), typename ... t
introduces a template parameter pack. -
In a parameter-declaration-clause (func(parameter-list)),
T ... t
introduces a function parameter pack. -
Ellipsis
...
appears immediately after a parameter name introduces parameter pack expansion
-
In a template-parameter-list (template
-
Fold Expression
- 1) Unary right fold (E op ...) becomes (E1 op (... op (EN-1 op EN)))
- 2) Unary left fold (... op E) becomes (((E1 op E2) op ...) op EN)
- 3) Binary right fold (E op ... op I) becomes (E1 op (... op (EN−1 op (EN op I))))
- 4) Binary left fold (I op ... op E) becomes ((((I op E1) op E2) op ...) op EN)
-
parameter_pack.cc
Variant, Optional, Any ¶
- std::optional is a wrapper that may or may not hold an object.
- std::any is a type that may hold an object of an arbitrary type.
-
std::variant is a type-safe union.
-
variant.cc
-
Scope Resolution Operator :: ¶
-
::func()
call only in global space, ignore others -
foo::func()
call inside anyfoo
namespace I can see -
::foo::func()
call only in test namespace, ignore others -
func()
call this func I can see -
using foo::func
can bring other possible functions to current namespace-
scope-operator.cc
-
Overload and Override ¶
-
Compile-time polymorphism
- If two overloads are equal, non-template function is preferred over template function.
- Overloads fail when only return type is different unless you use Covariant Return Types
-
Run-time polymorphism
- virtual function override
- Tutorial
Smart Pointer ¶
-
unique_ptr
-
Unique ownership so
Move-only
-
Unique ownership so
-
shared_ptr
- Simple reference counting
-
weak_ptr
- It tells you when the pointer is dangle. Control object is destroyed but control block is still alive.
-
It is just a ticket to get a shared_ptr by using
sptr = wptr.lock()
-
std::enable_shared_from_this()
- A class pointer becomes its own ticket to get a shared pointer. Maybe?
- If member function of a class is going to extent the class life time dynamically, use this.
-
Rules of thumbs
-
Treat smart pointer just as regular pointer
- Pass by value
- Return by value
-
A function/class taking a
unique_ptr
by value showstransfer of the ownership
-
Prefer
make_unique
over directly usingnew
-
Treat smart pointer just as regular pointer
- Tutorial
-
Tips
:-
variable declaration inside if condition
-
if (auto sptr = wptr.lock()) { Use(sptr); }
-
if (D *deriv_ptr = dynamic_cast<D*>(base_ptr)) { UseDerive(deriv_ptr); }
-
-
variable declaration inside if condition
Template instantiation and specialization ¶
-
Instantiation
- Substitute function parameters
- Compiler does implicit instantiation, which only instantiate used member functions of a template class
- Explicit instantiation will trigger complier to instantiate all member functions
-
Specialization
- Substitute function implementations
-
Explicit specialization can also be used to prevent other types to be specialized (we can also use Concepts to do this now)
-
explicit_instantiation.cc
-
explicit_specialization.cc
-
Constexpr ¶
Tips
:
-
constexpr
variables are stack values. They may not be evaluated at compile time (see this) . -
Most of time, you want
static constexpr
to define a constexpr variable.- Force evaluated at compile time
-
However, you can't declare a
static constexpr
inside aconstexpr
function.
C++ STL ¶
chrono
¶
- A precision neutral library for time and date.
-
Clock:
-
std::chrono::system_clock
: shows current time according to the system (manually changeable). -
std::chrono::steady_clock
: goes at a uniform rate. -
std::chrono::high_resolution_clock
: provides smallest possible tick period. -
std::chrono::steady_clock::period
: is astd::ratio
. -
std::chrono::duration<>
: represents time duration, -
std::chrono::time_point<>
: represents a point of time.
-
chrono.cc
Containers ¶
-
Sequence containers
-
vector:
- Fast insert/remove at the end: O(1)
- Slow insert/remove at the beginning or in the middle: O(n)
- Slow search: O(n)
-
Contiguous memory:
T* ptr = &vec[0]
-
Random access:
vec[i]
-
deque
- Fast insert/remove at the beginning and end: O(1)
- Slow insert/remove in the middle: O(n)
- Slow search O(n)
-
Random access:
deq[i]
-
list (double linked list)
- Fast insert/remove: O(1)
- Slow search O(n)
- No random access
- forward list
-
array
- std::array<Type, Size>
-
Contiguous memory:
T* ptr = &arr[0]
orT* ptr = arr.data()
-
Random access:
arr[i]
-
vector:
-
Associative Containers (binary tree, always sorted)
-
set
-
.insert()
Fast insertion: O(log(n)) -
.erase()
Fast removal: O(log(n)) -
.find()
Fast search: O(log(n)) - No random access
- No duplicated elements
-
Use equivalence
!(a<b) && !(b>a)
- Read-only
- Traversing is slower than Sequence containers
-
-
multiset
-
No insertion failures
multiset.cc
-
-
map
-
std::map<Key, Value>
-
-
multimap
-
multimap.cc
-
-
set
-
Unordered Containers (hash table)
-
unordered_set
- Fast insertion, removal, and search O(1)
- unordered_mutiset
-
unordered_map
unordered_map.cc
-
unordered_multimap
-
unordered_set
-
Container Adaptor
- stack
- queue
- priority_queue
Tips
:
-
Insert or Erase operations will invalidates array based containers, e.g. vector, deque
container_removal.cc
Iterators ¶
-
Random Acess Iterators: vector, deque, array
-
std::vector<T>::iterator iter
:iter++
,iter--
,iter += 2
-
-
Bidirectional Iterators: list, set, map
-
iter++
,iter--
-
-
Forward Iterator: forward_list:
-
iter++
-
- Unordered containers provide at least forward iterators
-
Input Iterator
- read and process values while iterating forward
-
Output Iterator
- output values while iterating forward
-
Const Iterator
-
`std::vector
::const_iterator
-
`std::vector
-
Iterator functions:
-
std::advance
,std::distance
,std::next
-
-
Iterator Adaptor
-
Insert Iterator
insert_iterator.cc
- Stream Iterator
- Reverse Iterator
- Move Iterator
-
Functors ¶
-
Build-in functors
-
std::less<T>()
,greater
,less_equal
,not_equal_to
,logical_and
,multiplies
,plus
,modulus
, etc.
-
Tips
:
-
mutable
lambda function.
Algorithms ¶
-
Mostly used to replace loops
-
std::min_element
,std::sort
,std::copy
,std::reverse
,std::find_if
,std::remove_if
-
-
Non-modifying algorithms
-
Counting:
-
count
,count_if
,
-
-
Min and Max:
-
min_element
(first min),max_element
(first max),minmax_element
(first min, last max),
-
-
Linear Search:
-
find
,find_if
,find_if_not
,search_n
,search
,find_end
,find_first_of
,adjacent_find
-
-
Comparing Ranges:
-
equal
,is_permutation
,mismatch
,lexicographical_compare
-
-
Check Attributes:
-
is_sorted
,is_sorted_until
,is_partitioned
,is_heap
,is_heap_until
,all_of
,any_of
,none_of
-
-
Counting:
-
Modifying algorithms
-
Copy:
-
copy
,copy_if
,copy_n
,copy_backward
-
-
Move: (If move semantics are not defined, copy will be used.)
-
move
,move_backward
-
-
Transform:
-
std::transform()
-
transform.cc
-
-
Swap:
-
swap_ranges
-
-
Fill:
-
fill
,fill_n
,generate
,generate_n
-
-
Replace:
-
replace
,replace_if
,replace_copy
,replace_copy_if
-
-
Remove:
-
remove
,remove_if
,remove_copy
,remove_copy_if
,unique
(remove consecutive elements),unique_copy
-
-
Order-changing
-
reverse
,reverse_copy
,rotate
,rotate_copy
,next_permutation
,prev_permutation
,random_shuffle
,shuffle
-
-
Copy:
- Sorting
Type Traits ¶
-
Conditional compilation
-
type_traits.cc
-
-
Altering types
-
std::remove_const
,std::add_const
,std::conditional
,std::conjunction
-
Concepts ¶
String View ¶
Filesystem ¶
Tips
:
-
Efficient insertion in vector:
vec.insert(vec.end(), vec2.begin(), vec2.end())
instead ofstd::copy(vec2.begin(), vec2.end(), std::back_inserter(vec))
C++ Design ¶
- Composition is preferred over inheritance for code reuse purpose.
C++ Core Guideline Tips ¶
Interfaces ¶
-
I.2 Avoid non-const global variables.
-
I.4 Make interfaces precisely and strong typed.
-
I.5 State preconditions in callee if the arguments have meaning that might constrain their proper use.
- E.g. using Expects
-
I.7 State postconditions before function returns.
- E.g. using Ensures
-
I.11 Never transfer ownership by a raw pointer (T*) or reference (T&).
-
Pass ownership use smart pointers or
gsl::owner
. - Every object passed as a raw pointer (or iterator) is assumed to be owned by the caller, so that its lifetime is handled by the caller.
-
Pass ownership use smart pointers or
-
I.12 Declare a pointer that must not be null as
not_null
.-
Use
gsl::not_null
.
-
Use
-
I.13 Do not pass an array as a single pointer.
-
Use
gsl::span
orstd::span
-
Use
-
I.23 Keep the number of function arguments low (<5).
- Use default parameters or overloads
-
I.24 Avoid adjacent parameters that can be invoked by the same arguments in either order with different meaning.
-
I.25 Prefer empty abstract classes as interfaces to class hierarchies
-
I.27 For stable library ABI, consider the Pimpl idiom.
impl_idiom.cc
-
Tips
-
Always mark constructor as
explicit
when it only takes a single argument. -
Use
Rule 0
orRule 5
when defining compiler generated class functions. - A polymorphic class should suppress public copy/move.
-
Always mark constructor as
Guideline Support Library (gsl) ¶
Unit Test ¶
Test Driven Development ¶
GoogleTest ¶
-
Macros:
-
Nonfatal assertion
-
EXPECT_EQ(expected, tested)
,EXPECT_TRUE() << "Error message"
,EXPECT_STREQ
-
-
Fatal assertion
-
ASSERT_EQ()
,ASSERT_TRUE()
-
-
Floating
-
EXPECT_FLOAT_EQ()
,EXPECT_NEAR()
-
-
Nonfatal assertion
-
Death test
-
TEST(mapping_DeathTest, simple_test) {}
: Death tests run before other tests -
EXPECT_DEATH
,EXPECT_EXIT
-
-
Exception test
-
TEST(mapping_ExceptionTest)
-
EXPECT_THROW
,EXPECT_ANY_THROW
,EXPECT_NO_THROW
,FAIL()
-
-
TestFixture
-
Common setup for a group of tests
-
class MappingTest : public ::testing::Test {public: virtual void SetUp(); virtual void TearDown();}
-
TEST_F(MappingTest, simple_test)
-
-
Common setup for a group of tests
BoostTest ¶
Building System and Generators ¶
-
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DCMAKE_INSTALL_PREFIX " " ..
-
cmake --build .
-
cmake --install . --prefix "/home/myuser/installdir"
-
Modern cmake module properties
-
PUBLIC
: both the producer and consumer see the definition -
PRIVATE
: only the producer sees the definition -
INTERFACE
: only the consumer see the definition
-
-
Useful build-in commands and variables
-
cmake_minimum_required(VERSION 3.12)
-
project(MyProject VERSION 0.0.0)
-
add_subdirectory()
-
add_executable
-
add_library
-
target_link_libraries
-
target_include_directories
-
target_compile_definition
-
target_compile_features
: feature list -
${CMAKE_SOURCE_DIR}
: Top level of the source tree -
${CAMKE_BINARY_DIR}
: Top level of the build tree -
${PROJECT_NAME}$
,${PROJECT_SOURCE_DIR}
,${PROJECT_BINARY_DIR}$
-
${CMAKE_CURRENT_SOURCE_DIR}
: Source directory of the current cmake file -
${CMAKE_CURRENT_LIST_FILE}
-
-
script
-
set(MY_VARIABLE "variable")
-
message(STATUS "hello world ${MY_VARIABLE}")
-
if() endif()
-
foreach(arg IN LIST ARGN/ARGV) endforeach()
-
function() endfunction()
-