[C++]Advanced Features Notes
keywords: C++, Advanced Features Notes, Tutorials
Fragments
Dependency Injection
Dependency Injection in C++
https://vladris.com/blog/2016/07/06/dependency-injection-in-c.html
Anonymous Namespaces
Unnamed/anonymous namespaces vs. static functions
https://stackoverflow.com/questions/154469/unnamed-anonymous-namespaces-vs-static-functions
Dynamic Initialization & Static Initialization
C++ - Initialization of Static Variables
https://pabloariasal.github.io/2020/01/02/static-variable-initialization/
constexpr vector and string in C++20 and One Big Limitation
https://www.cppstories.com/2021/constexpr-vecstr-cpp20/
Polymorphic Allocator
std::pmr::polymorphic_allocator
https://en.cppreference.com/w/cpp/memory/polymorphic_allocator
polymorphic_allocator: when and why should I use it?
https://stackoverflow.com/questions/38010544/polymorphic-allocator-when-and-why-should-i-use-it
Polymorphic Allocators, std::vector Growth and Hacking
https://www.bfilipek.com/2020/06/pmr-hacking.html
Call Stack
print call stack in C or C++
https://stackoverflow.com/a/54365144/1645289
Comment
pragma region example:
// pragma_directives_region.cpp
#pragma region Region_1
void Test() {}
void Test2() {}
void Test3() {}
#pragma endregion Region_1
int main() {}
Platform
Endianness (Byte Order)
Let’s say your data stream has a little-endian-encoded 32-bit integer. Here’s how to extract it (assuming unsigned bytes):
i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
If it’s big-endian, here’s how to extract it:
i = (data[3]<<0) | (data[2]<<8) | (data[1]<<16) | (data[0]<<24);
Origin:
How do I convert between big-endian and little-endian values in C++?
https://stackoverflow.com/a/10346064/1645289
Performance
Move Semantics
What is move semantics?
https://stackoverflow.com/questions/3106110/what-is-move-semantics
Difference between copy constructor and move constructor
https://stackoverflow.com/a/3106136/1645289
Exception
There is a cost associated with exception handling on some platforms and with some compilers.
Namely, Visual Studio, when building a 32-bit target, will register a handler in every function that has local variables with non-trivial destructor. Basically, it sets up a try/finally
handler.
The other technique, employed by gcc and Visual Studio targeting 64-bits, only incurs overhead when an exception is thrown (the technique involves traversing the call stack and table lookup). In cases where exceptions are rarely thrown, this can actually lead to a more efficient code, as error codes don’t have to be processed.
Quoted from:
In what ways do C++ exceptions slow down code when there are no exceptions thown?
https://stackoverflow.com/a/1897979/1645289
std::align (alignas & alignof)
Little C++ Standard Library Utility: std::align
https://lesleylai.info/en/std-align/
Compilation
How to use two libraries if they have same function in C
If you have .o files there, a good solution:
objcopy --prefix-symbols=pre_string test.o to rename the symbols in .o file
or
objcopy --redefine-sym old_str=new_str test.o to rename the specific symbol in .o file.
Origin:
https://stackoverflow.com/a/41375697/1645289
C
Memory
Why is the use of alloca() not considered good practice?
https://stackoverflow.com/questions/1018853/why-is-the-use-of-alloca-not-considered-good-practice
STL
new(std::nothrow)
std::nothrow
https://en.cppreference.com/w/cpp/memory/new/nothrow
lock_guard (RAII)
std::mutex m;
void bad()
{
m.lock(); // acquire the mutex
f(); // if f() throws an exception, the mutex is never released
if(!everything_ok()) return; // early return, the mutex is never released
m.unlock(); // if bad() reaches this statement, the mutex is released
}
void good()
{
std::lock_guard<std::mutex> lk(m); // RAII class: mutex acquisition is initialization
f(); // if f() throws an exception, the mutex is released
if(!everything_ok()) return; // early return, the mutex is released
}
Origin:
https://en.cppreference.com/w/cpp/language/raii
Lambda
this vs &
C++ lambda capture this vs capture by reference
https://stackoverflow.com/questions/33575563/c-lambda-capture-this-vs-capture-by-reference
= VS & (Value vs Reference)
Quick example
int x = 1;
auto valueLambda = [=]()
{
cout << x << endl;
};
auto refLambda = [&]()
{
cout << x << endl;
};
x = 13;
valueLambda();
refLambda();
Output:
1
13
Is there any difference betwen [=] and [&] in lambda functions?
https://stackoverflow.com/a/21105182/1645289
shared_ptr with Lambda
C99
template<typename T, typename F>
class shared_this_lambda {
std::shared_ptr<T> t; // just for lifetime
F f;
public:
shared_this_lambda(std::shared_ptr<T> t, F f): t(t), f(f) {}
template<class... Args>
auto operator()(Args &&...args)
-> decltype(this->f(std::forward<Args>(args)...)) {
return f(std::forward<Args>(args)...);
}
};
template<typename T>
struct enable_shared_this_lambda {
static_assert(std::is_base_of<std::enable_shared_from_this<T>, T>::value,
"T must inherit enable_shared_from_this<T>");
template<typename F>
auto make_shared_this_lambda(F f) -> shared_this_lambda<T, F> {
return shared_this_lambda<T, F>(
static_cast<T *>(this)->shared_from_this(), f);
}
template<typename F>
auto make_shared_this_lambda(F f) const -> shared_this_lambda<const T, F> {
return shared_this_lambda<const T, F>(
static_cast<const T *>(this)->shared_from_this(), f);
}
};
Usage
doSomethingAsynchronously(make_shared_this_lambda([this] {
someMember_ = 42;
}));
Orgin: Using C++11 lambdas asynchronously, safely
weak_ptr with Lambda
Example:
std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>([thisWeakPtr]()
{
auto myPtr = thisWeakPtr.lock();
if(myPtr)
myPtr->CallbackFunc()
});
Origin: Binding to a weak_ptr
Error C2663 : 2 overloads have no legal conversion for ’this’ pointer
Case 01:
void Process(FRDGBuilder& Builder)
{
AsyncLoad([Builder](FRenderData& Data) //this fires compilation error
{
Builder.CreatBuffer(Data);
});
}
Compiliation error:
error C2663: 'FRDGBuilder::CreateBuffer': 2 overloads have no legal conversion for 'this' pointer
Solution:
void Process(FRDGBuilder& Builder)
{
AsyncLoad([&Builder](FRenderData& Data)
{
Builder.CreatBuffer(Data);
});
}
Type support
offsetof
The macro offsetof
expands to an integral constant expression of type std::size_t, the value of which is the offset, in bytes, from the beginning of an object of specified type to its specified subobject, including padding bits if any.
References:
Type support (basic types, RTTI)
https://en.cppreference.com/w/cpp/types
Reference
Blogs
Barry Revzin (Recommended)
https://brevzin.github.io/
Modernes C++
https://www.modernescpp.com/index.php/
Categories for the Working C++ Programmer
https://bartoszmilewski.com/2020/08/05/categories-for-the-working-c-programmer/amp/
<bit> in Visual Studio 2019 version 16.8 Preview 2
https://devblogs.microsoft.com/cppblog/bit-in-visual-studio-2019-version-16-8-preview-2/
Rank does not confer privilege or give power. It imposes responsibility. ― Peter Drucker