Skip to content

Latest commit

 

History

History

Util

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Util

Prefer STL Algorithms over Raw Loops

void lower(std::string s) {
    for (unsigned int i = 0; i <= std::strlen(s.data()); ++i) {
        s[i] = std::lower(s[i]);
    }
}

std::transform(s.begin(), s.end(), s.begin(), [](char c) { return std::tolower(c); });

Prefer Immutable Data to Mutable Data

  • Easier to verify code when using constants.
  • Constants have higher optimization potential.
  • Constant data is data-race free by design, since mutation is a necessary condition for a data-race.

About

Contains template (generic) function in a C-style header file, providing the following functionality:

  • is_instance_of.hpp
    • definition
    • unit tests
    • identify whether an object if of a specified type.
    • comparable to isinstance() in Python.
  • is_same_type_of.hpp
    • definition
    • identify whether two objects are the same type.
    • use typeid().hash_code() and typeid().name().
  • log.h
    • definition
    • function-style definition LOG(...) using macro in C.
  • parse.hpp
  • print_list.hpp
    • definition
    • template function to print a std::list<> to console.
    • accepts a generic type of std::list<>.
  • print_range.hpp
    • definition
    • unit tests
    • template function to print a std::ranges<> to console.
    • accepts a generic type of std::ranges<>.
  • print_vec.hpp
    • definition
    • template function to print a std::vector<> to console.
    • accepts a generic type of std::vector<>.
  • safe_free.hpp
  • trimstr.hpp

cpp Language Reference and Notes

& and && overload operators thoughts experiment - Reference Qualifiers

  • Consider the & and && operator overloads either with const qualifications or not as "invoked with"
    • For example, &concrete_instance shall be considered as "such function is invoked with a lvalue"
      Consider the following example: https://github.com/XuhuaHuang/EmbeddedProgramming/blob/main/MemberFnAmpersand/MemberFnAmpersand.cpp
      • The function with the signature int& getArg()& is invoked with a mutable lvalue (left value)
      • The function with the signature int& getArg()&& is invoked with a mutable rvalue (right value)
    • Such mentality will also make sense for a normal operation like the following;
      • int* p_int = &int_on_stack;
        In this case, the & operator is "invoked with" a lvalue
      • std::string str = std::move(another_std_str);
        In this case, std::move(std::string&& src) is "invoked with" a (pure) rvalue

Arithmetic and Comparison Operators Support

template<typename Type>
struct support_stdspan_arithmetic_operators {
    using value_type = std::remove_cv_t<Type>;
public:
    inline constexpr friend std::span<value_type> operator + (std::span<value_type> lhs, const value_type n)
    {
        std::span<value_type> copy{ lhs };
        for (/* std::span<value_type>::iterator */ constexpr auto it = copy.begin(); it != copy.end(); it++) {
            *it += n;
        }
        return std::span<value_type>(copy);
    }
};

struct long_double_span_arithmetic_operators : support_stdspan_arithmetic_operators<long double> {};

struct double_span_arithmetic_operators : support_stdspan_arithmetic_operators<double> {};

template<typename Type>
struct support_stdspan_comparison_operators {
    using value_type = std::remove_cv_t<Type>;
public:
    constexpr support_stdspan_comparison_operators() = default;
    template<typename value_type>
    friend constexpr bool operator == (std::span<value_type> lhs, std::span<value_type> rhs) { return true; }
};

struct double_span_comparison_operator : support_stdspan_comparison_operators<double> {};

Include Gard

#if defined(__has_include) && __has_include(<version>)
#include <version>
#endif

Design by Introspection

consteval decltype(auto) foo(auto t) {
    if constexpr (requires{ t.foo; }) {
        return t.foo;
    } else {
        return 0;
    }
}

constexpr struct { int foo{42}; } f;
static_assert(42 == foo(f));

constexpr struct { int bar{42}; } b;
static_assert(0 == foo(b));

Immediately-Invoked Function Expression (IIFE)

#include <iostream>
#include "unroll.hpp"

int main(void) {
    util::iife::unroll<2>([]{ std::puts("Hello C++ 20!"); });
    return 0;
}

std::valarray::swap and std::addressof Implementation

void swap(valarray& _Right) noexcept {
    if (this != _STD addressof(_Right)) {
        _STD swap(_Myptr, _Right._Myptr);
        _STD swap(_Mysize, _Right._Mysize);
    }
}

_EXPORT_STD template <class _Ty>
_NODISCARD constexpr _Ty* addressof(_Ty& _Val) noexcept {
    return __builtin_addressof(_Val);
}

_EXPORT_STD template <class _Ty>
const _Ty* addressof(const _Ty&&) = delete;

Typical get_data() Function Implementation with Variadic Template Parameter Pack

#include <array>

template<typename ValueType, typename ... Params>
[[nodiscard]] std::array<ValueType, sizeof...(Params)+1> get_data(const ValueType& v1, const Params& ... params)
{
    return {v1, params...};
}

/// @brief C++17 Implementation with CTAD
template<typename ValueType, typename ... Params>
auto get_data(const ValueType& v1, const Params& ... params)
{
    return std::array{v1, params...};
}

auto get_data(auto&& ... params)
{
    return std::array{std::forward<decltype(params)>(params)...};
}

An Easy-to-read invocable Concept

template<typename Fn, typename... Args>
concept my_invocable = requires (Fn&& fn, Args&&... args) {
    std::invoke(std::forward<Fn>(fn), std::forward<Args>(args)...);
}