C Plus Plus

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
  • 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 any foo 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
  • 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 shows transfer of the ownership
    • Prefer make_unique over directly using new
  • 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); }

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

- Tutorial Tutorial

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 a constexpr 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 a std::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] or T* ptr = arr.data()
      • Random access: arr[i]
  • 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
  • Unordered Containers (hash table)

    • unordered_set
      • Fast insertion, removal, and search O(1)
    • unordered_mutiset
    • unordered_map

      unordered_map.cc
    • unordered_multimap

  • 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
  • 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
  • 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
  • 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 of std::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.

  • I.7 State postconditions before function returns.

  • 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.
  • I.12 Declare a pointer that must not be null as not_null .

    • Use gsl::not_null .
  • I.13 Do not pass an array as a single pointer.

    • Use gsl::span or std::span
  • 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

Guideline Support Library (gsl)

gsl::span

gsl_span.cc

gsl::not_null

gsl_span.cc

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()
  • 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)

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()
This blog is converted from c_plus_plus_notes.ipynb
Written on February 2, 2022