Work and Note

Cpp Misc

Follow me on GitHub

basic

  • [[nodiscard]]: mark a value so that user cannot ignore it without notice
  • remove while iterating
    • erase() return iter to next element
  • comp functor requires a strict weak ordering
    • i.e. implement < rather than <=

preprocessor

# // stringizing
## // token pasting

Reference

Note: If an argument is stringized or concatenated, the prescan does not occur. i.e. macro argument is not marco-expanded before substitution.

#define xstr(s) str(s)
#define str(s) #s
#define foo 4
str (foo)
      "foo"
xstr (foo)
      xstr (4)
      str (4)
      "4"

[Reference])(https://gcc.gnu.org/onlinedocs/gcc-7.5.0/cpp/Argument-Prescan.html#Argument-Prescan)

static and const

  • static means that variable will be shared, which can still be changed in runtime.
    • Thus, require a storage space and cannot be defined in a header file
    • (c++17 has inline variable)
  • const means that the value cannot change after creation
  • static const means that the value is a constant, which will evaluated during compilation
    • intergral constant has special rules called integral constant expressions
    • for other type, we need specify constexpr in the type
      • constexpr implicitly make the type to be const
      • constexpr does not make sense on type without static
      • constexpr only works on literal type or reference type
        • no object?
  • When use constexpr in expression, programmer need to make sure that the expression can be evaluated at compile time

array type

There is an implicit conversion from lvalues and rvalues of array type to rvalues of pointer type: it constructs a pointer to the first element of an array. This conversion is used whenever arrays appear in context where arrays are not expected, but pointers are.

Note that when array-to-pointer decay is applied, a multidimensional array is converted to a pointer to its first element (e.g., a pointer to its first row or to its first plane): array-to-pointer decay is applied only once.

Notice that new [] always seems to decay once.

Demo Here

stdio

  • cin stops at whitespace (w/o removing them)
    • cin ignores leading whitespace
  • getline remove newline from stream
    • cin.ignore() to remove character from stream
    • cin.ignore(80, 'b') remove upto 80 char until b is also consumed
  • string + stringstream + std::getline == split
    • getline can use a single char as delim
// makes c and c++ io have independent buffer
ios_base::sync_with_stdio(false);
// normally, cin / cout flush before operation on the other stream
// untie it means manually flush
cin.tie(NULL);

incompleted type

A structure type whose members you have not yet specified. A union type whose members you have not yet specified. An array type whose dimension you have not yet specified.

  • EXP57-CPP: do not delete pointers to incomplete classes
  • For the following case, the compiler is forced to generate a deleter
  • unique_ptr: zero-abstraction -> deleter always generated.
    • ~P()
    • move assignment
    • reset()
    • reset(A*)
  • shared_ptr: deleter is needed to construct the control block
    • P(A*)
    • reset(A*)

complete type requirement

virtual function

  • virtual function should be accessed using pointer or reference
  • function call might not be inlined because of vtable
    • it is possible if the type can be determined
  • implementation:
    • each class has a static virtual table
    • each virtual object holds a pointer to some virtual table
    • at construction, replace parent’s pointer with child’s pointer
    • type information & dynamic cast can be embedded in the virtual table
// simple dump function
// %zu for size_t, %p for void *
static void print_object(const char *name, void *this_, size_t size) {
  void **ugly = reinterpret_cast<void**>(this_);
  size_t i;
  printf("created %s at address %p of size %zu\n", name, this_, size);
  for(i = 0 ; i < size / sizeof(void*) ; i++) {
    printf("  pointer[%zu] == %p\n", i, ugly[i]);
  }
}

http://blog.httrack.com/blog/2014/05/09/a-basic-glance-at-the-virtual-table/

multi-threading

  • use scoped_lock over lock_guard because it is a super set
  • unique_lock has the state of not owning any mutex.
    • Thus, it can be default constructed. (error-prune)
  • condition_variable:
    • needs to unlock so unique_lock is necessary
    • w/o predicate, a cv can be notified before entering wait state (lost)
      • with predicate, we can check and skip the wait
    • w/o predicate, a cv can Spurious wakeup and escape the wait
      • with predicate, we will re-enter wait
    • predicate needs to be guarded with the same mutex
      • otherwise, a sync is not guaranteed.

iterator

  • when empty, then begin() == end()
  • input iterator, ++r requires r to be dereferencable
  • bidirectional iterator, --r has the post condition that r is dereferenable
  • before_begin is only defined for forward_list

std::algorithm

  • find_if, find_if_not
    • find_first_of, find_last_of in std::string has a pos parameter
  • swap, reverse

namespace

  • anonymous namespace has internal linkage which is the same as static in file
  • inline namespace expose content to enclosing namespace
    • inject information into the mangled name (ABI) without altering the API
      • used for library versioning
      • ADL does not follow using
    • default call accesses inline namespace
    • but a fully qualified call can access any namespace
      • old abi is retained
    • as long as the type does not cross api boundary, a executable can use both namespaces at the same time

inline keyword

  • inline allow function to defined in multiple tranlation unit
    • but we must make sure that all definition match
  • since c++17, inline can also be used on variable
    • that means static variable does not need a separated cpp file

exception

  • prefere a separate Init() and DeInit()
    • exception is the only way for constructor to fail
      • but only allocation fail is reasonable for constructor
    • deconstructor should not throw exception in any cases
  • all exceptions need to be exposed in abi
    • otherwise, rtti cannot resolve the inheritance chain
  • exceptions need to be inherited virtually such that it resolve to a single base class

noexcept

  • when throwing a exception, the programm will call std::terminite
  • noexcept on move constructor can improve performance
  • conditional noexcept can be used in template class

reflection vs rtti

With rtti, program is able to work on a set of runtime types. The set is determined in compile time.

With reflection, program is expected to work on any runtime types by looking into the data structure during runtime

virtual function in cpp constructor / destructor [OOP50-CPP]

the function called is the final overrider in the constructor’s or destructor’s class and not one overriding it in a more-derived class.

During the construction process, the vtable pointer is changed when entering a child class scope. So, virtual function cannot resolve to correct function.

(Also, member variable does not exist at this point)

INT02-C

Integer types smaller than int are promoted when an operation is performed on them

If the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

attribute

[[deprecated]]

gMock

  • dependency injection
    • differennt use case might require vastly different contruction parameter
    • inject mock class when testing
  • but virutal mock class create inheritance that should not exist
    • static injection via template
    • c++ 20 cocepts
  • vs factory / delegation
    • instead of inject object, let the class create it as needed
    • factory allow more procedure calls than constructor

todo section

c++ module

https://vector-of-bool.github.io/2019/03/31/modules-2.html

c++ guide? https://developer.mozilla.org/en-US/docs/Mozilla/Using_CXX_in_Mozilla_code

c++ regex

vs rust regex?

some nice source

Guru of the Week Bartek’s coding blog cppinsights compiler explorer

C++ Core Guidelines Common Weakness List SEI CERT C++ MISRA Abseil Guide