Showing posts with label code_study. Show all posts
Showing posts with label code_study. Show all posts

Nov 9, 2025

[C++] Use string_view _sv over raw char string

Reference:
https://youtu.be/jXQ6WtYmfZw?si=B_C-UXBVCFpAODVh&t=4428


std:: string s("the foo and the bar");
std:: println("{}", std::ranges::contains_subrange(s, "foo" ));
This won't work due to C-style string literal "foo" is actually a range of four characters: 
['f', 'o', 'o', '\0'] 

Easy fix:
#include <iostream>
#include <string>
#include <string_view>
#include <ranges>
#include <print> // C++23 for std::println

int main() {
    using namespace std::literals; // Enables the "sv" suffix

    std::string s("the foo and the bar");
    
    // "foo"sv creates a std::string_view of length 3.
    // This will now print "true".
    std::println("{}", std::ranges::contains_subrange(s, "foo"sv)); 
}

or C++23:
std::string s("the foo and the bar");

// This is the simplest way and does what you expect.
// It will print "true".
std::println("{}", s.contains("foo"));

Oct 17, 2025

[C++][template] Double checked Stop technique

godbolt:
https://godbolt.org/z/Yenv16xzj

#include <functional>
#include <iostream>
#include <optional>


template <size_t I, typename F>
constexpr std::optional<int> ApplyIndexForOverflow(F f) {
    return ApplyIndexForOverflow<I - 1>(f);
}

template <size_t I, typename F>
constexpr std::optional<int> ApplyIndexFor(F f) {
    if (I == 0) {
        return std::nullopt;
    }
    // double checked stop; otherwise introduced stack overflow
    // from the compiler runtime due to has to instantiate
    // unbounded template instance, like above `ApplyIndexForOverflow`
    return ApplyIndexFor<(I == 0 ? 0 : I - 1 )>(f);
}

template <size_t I, typename F>
constexpr std::optional<int> ApplyIndexForConstexpr(F f) {
    if constexpr(sizeof(F) == 1){
        return I;
    }
    if constexpr(I - 1 == 0){
        return std::nullopt;
    } else {
        return ApplyIndexForConstexpr<I-1>(f);
    }
}

int main() {
 auto run = []{};
 ApplyIndexForOverflow<100>(run);
 ApplyIndexFor<100>(run);
 ApplyIndexForConstexpr<100>(run);
}

Jul 28, 2024

[C++] tag pointer

Reference:
Storing data in pointers

#include <cstddef>
#include <cstdint>
#include <iostream>


enum ListType {
  kNone,
  kReady,
  kDeleting,
};


static constexpr uintptr_t kListTypeMask = 0b11;
static constexpr uintptr_t kCleanPtrMask = ~kListTypeMask;

struct Tree;

struct Node{
  void set_list_type(ListType list_type) {
    uintptr_t t = static_cast<uintptr_t>(list_type);
    uintptr_t v = ptr_and_list_type_ & kCleanPtrMask;
    ptr_and_list_type_ = (v | t);
  }

  ListType list_type() const {
    return static_cast<ListType>(ptr_and_list_type_ & kListTypeMask);
  }

  void set_prev_next_ptr(Node** p) {
    uintptr_t t = ptr_and_list_type_ & kListTypeMask;
    uintptr_t v = reinterpret_cast<uintptr_t>(p);
    ptr_and_list_type_ = (v | t);
  }

  Node** prev_next_ptr() const {
    return reinterpret_cast<Node**>(ptr_and_list_type_ & kCleanPtrMask);
  }

  Tree* tree_ = nullptr;
  Node* parent_ = nullptr;
  Node* next_ = nullptr;
  uintptr_t ptr_and_list_type_ = 0;
};

struct Tree{
  void MarkReady(Node* p) {
    p->next_ = ready_;
    p->set_prev_next_ptr(&ready_);

    if (ready_ != nullptr) {
      ready_->set_prev_next_ptr(&p->next_);
    }

    ready_ = p;
    p->set_list_type(kReady);
  }
 
  int padding;
  Node* ready_ = nullptr;
};


int main() {
  // Print 8 since padding is type of int occupies 8 bytes.
  std::cout << "offset of ready_: " <<
    reinterpret_cast<void*>(&((Tree*)0)->ready_) << "\n";

  Tree* tree = new Tree{};
  std::cout << "tree: " << reinterpret_cast<void *>(&tree) << "\n";
  std::cout << "tree offset of ready: " <<
    reinterpret_cast<void *>(&tree->ready_) << "\n";

  Node p;
  p.tree_ = tree;
  tree->MarkReady(&p);
  std::cout << reinterpret_cast<void *>(p.prev_next_ptr()) << "\n";
}

MSB tagging vs. LSB tagging

May 10, 2023

[C++] SFINAE for testing type convertible

Reference:
https://en.cppreference.com/w/cpp/types/is_convertible
[C++][cppcon 2017] Write our own type trait

Use function parameter type to test if a incoming argument type is implicitly convertible to parameter type.

This trick can be used in SFINAE to test type convertibility.

#include <type_traits>

struct O2 {};
struct O1 {
  O1() = default;
  O1(const O2 &) {}
};

int main() {
  // cannot be converted:
  // decltype(void(std::declval<void (&)(O2)>()(std::declval<O1>()))) A;
  decltype(void(std::declval<void (&)(O1)>()(std::declval<O2>()))) *A = nullptr;
};

Mar 24, 2012

[C++11][NOTE] Variadic Templates , Parameter Packs

template<typename… Types> // declare liststruct
Count; // walking template

template<typename T, typename… Rest> // walk list
struct Count<T, Rest…>
{
const static int value = Count<Rest…>::value +1;
};

template<> struct Count<> // recognize end of
{ // list
const static int value = 0;
};

auto count1 = Count<int, double, char>::value; // count1 = 3
auto count2 = Count<>::value; // count2 = 0