Eugene Hutorny
type: channel
description: Programming in a small
date: 2026-01-31T07:39:01Z
update period: hourly
update frequency: 1
update base: 2000-01-01T12:00+00:00
generator agent: https://wordpress.org/
items: Practical C++26 reflection for Protobuf
items: Практична рефлексія C++26 для Protobuf
items: Off-target testing embedded projects with STUBMMIO
items: Logovod – macro-free allocation-free user-configurable logger front-end for C++
items: is_constexpr – a template to test if a function is constexpr
items: setof – an iterable set of strongly typed enumerations
items: C++ switch with textual cases
items: any_of<c1, …, c2>(v)
items: COJSON library for Arduino
items: cojson tutorial for C++17

Practical C++26 reflection for Protobuf
type: item
creator: Eugene
date: 2026-01-31T07:39:01Z
subject: C++
subject: C++26
subject: deserializer
subject: proto
subject: Protobuf
subject: reflection
subject: serializer
description: Abstract The new edition of the C++ standard [1], expected to be released in 2026, will add reflection to C++. This will allow developers to write code that will examine the properties of classes, types, functions, and other elements and make changes to them. At the time of writing, reflection is not supported by the […]
encoded: Abstract The new edition of the C++ standard [1], expected to be released in 2026, will add reflection to C++. This will allow developers to write code that will examine the properties of classes, types, functions, and other elements and make changes to them. At the time of writing, reflection is not supported by the main branches of compilers, but it is available in branches such as clang [2] and gcc, which can be build on user's own. For quick experiments, one can also use Compiler Explorer [A]. In review articles and videos on this topic, the most common example is printing arbitrary structures or serializing them in JSON. In this article, the author invites the reader to practice with a slightly more complex example -deserialization with protobuf. Overview Section Goals and Objectives outlines the goals and objectives, while the Instrumentarium section provides a brief overview of the reflection features that will be needed for our exercise. Section Protobuf briefly describes the serialization format. In the Design section, we will formulate the design rationales. In the Implementation section, we will write the code, and in Verification, we will outline the testing methodology. Section Conclusions will summarize the results of our exercises. The Discussion section will supplement the details regarding the intentions or motivations behind some aspects of the design and implementation. Goals and Objectives The purpose of this article is to write a solution for deserializing arbitrary messages in protobuf format with the possibility of using them in projects without dynamic memory (malloc-free). The main goal is to master new C++ features and familiarize readers with examples of their practical use. A secondary goal is to understand the Protobuf serialization format. Instrumentarium ^^expr the reflection operator - prefix ^^ - produces a reflection value from a grammatical construct - its operand expr. Reflection values — reflections for short - values of an opaqu…

Практична рефлексія C++26 для Protobuf
type: item
creator: Eugene
date: 2026-01-25T09:00:07Z
subject: C++
subject: C++26
subject: deserializer
subject: Protobuf
subject: reflection. proto
subject: serializer
description: Вступ Нова редакція стандарту C++ [1], випуск якої очікується у нинішньому, 2026 році, додасть в C++ рефлексію (reflection). Це дозволить розробникам писати код, який досліджуватиме властивості класів, типів, функцій, та інших елементів і робити у них зміни. На момент написання статті, рефлексія хоча і не підтримується основними гілками компіляторів, проте доступна у відгалуженнях як clang […]
encoded: Вступ Нова редакція стандарту C++ [1], випуск якої очікується у нинішньому, 2026 році, додасть в C++ рефлексію (reflection). Це дозволить розробникам писати код, який досліджуватиме властивості класів, типів, функцій, та інших елементів і робити у них зміни. На момент написання статті, рефлексія хоча і не підтримується основними гілками компіляторів, проте доступна у відгалуженнях як clang [2] так і gcc, які можна зібрати самостійно. Для експериментів нашвидкоруч можна також скористатись Compiler Explorer [A]. У оглядових статтях та відео на цю тему найпоширеніший приклад - друкування довільних структур чи їх серіалізація в JSON. В рамках цієї статті автор пропонує читачу повправлятися разом з автором із дещо складнішим прикладом - десеріалізацією із protobuf. Огляд Розділ Цілі та Мета окреслить мету і цілі, розділ статті Інструментарій дасть коротку довідку по фічах рефлексії, що знадобляться для нашої вправи. Розділ Protobuf коротко опише формат сералізації. У розділі Дизайн зформулюємо дизайн рішення. У розділі Імплементація ми напишемо код, а у Верифікація окреслимо методологію тестування. Розділі Підсумки узагальнить результати наших вправ. Розділ Дискусія доповнить деталями щодо намірів чи мотивації деяких аспектів дизайну та імплементації. Цілі та Мета Ціль цієї статті - написати рішення для десеріалізації довільних повідомлень у форматі protobuf з можливістю використання в проєктах без динамічної пам’яті (malloc-free). Основна мета - освоїти нові інструменти C++ та ознайомити читачів із прикладами їх практичного використання. Побічна мета - розібратися із форматом серіалізації Protobuf. Інструментарій ^^expr оператор рефлексії - префікс ^^ - обраховує і повертає значення рефлексії (метаоб’єкта) для заданого операнду expr. Значення рефлексії, або просто рефлексія - це значення непрозорого типу даних std::meta::info,яке можна використати у метафункціях для аналізу чи генерації граматичних конструкцій. [: refl:] Граматична конструкція зрощення (англ. splice) ро…

Off-target testing embedded projects with STUBMMIO
type: item
creator: Eugene
date: 2026-01-11T09:43:12Z
subject: C++
subject: Research
subject: cross-compile
subject: MMIO
subject: off-target testing
subject: unit-tests
description: Introduction Off-target testing - building and running tests "on a development host or build server rather than on the target hardware" . [3] stubmmio is a C++ library for off-target embedded unit tests by stubbing MCU’s MMIO regions on a Linux machine. Memory-mapped I/O (MMIO) is a method of performing I/O through registers, mapped to […]
encoded: Introduction Off-target testing - building and running tests "on a development host or build server rather than on the target hardware" . [3] stubmmio is a C++ library for off-target embedded unit tests by stubbing MCU’s MMIO regions on a Linux machine. Memory-mapped I/O (MMIO) is a method of performing I/O through registers, mapped to MCU’s address space [1]. stubmmio allows the users to substitute MMIO registers of interest with the host memory, setup the initial state of the stubbed MMIO registers, and verify their state against expected after running the code under test. Principle of Operation An off-target unit test: Assumes the code under test (CUT) has been compiled for the host and is callable from a C++ code Reserves MMIO address space (test arena) in the host process memory Maps MMIO-in-use with mmap Setups MMIO-in-use at the state, predefined by the running test case Runs CUT Validates MMIO state stubmmio provides classes to support this approach: stubmmio::stub to map the MMIO-in-use and setting up initial state stubmmio::verify to validate MMIO state stubmmio::stimulus to simulate simple asynchronous behaviour of the peripheral CUT Constraints Off-target embedded UT with stubmmio imposes the following constraints: CUT compiles for the host CUT is callable from C++ (e.g. written in C or C++) CUT does not have an infinite loop CUT does not relay or precise timing CUT does not expect complicated behaviour of the hardware Primary Classes stubmmio::stub stubmmio::stub is a collection of memory elements. A memory element is a continuous memory range staring at a given address. The stub memory elements usually have initial data. When a stub is applied, it allocates memory pages to for all its elements and writes initial element data. On destruction, stub deallocates all pages. Multiple stubmmio::stub instances are allowed, provided they refer to different host memory pages. A stubmmio::stub instance owns the allocated pages, so that other instances cannot use …

Logovod – macro-free allocation-free user-configurable logger front-end for C++
type: item
creator: Eugene
date: 2024-10-14T05:32:09Z
subject: C++
subject: Projects
subject: C++17
subject: logging
subject: macro-free
description: 1. Features logovod features Three styles of use — with functions, ostream left shifts, format string Automatic space insertion of functional style Automatic printing of standard containers, tuples, variants, optional Compile or run-time priority levels Compile or run-time sinks Constrained message length Support for wide-char streams Priority levels according to RFC-5424 section-6.2.1 2. Concerns The […]
encoded: 1. Features logovod features Three styles of use — with functions, ostream left shifts, format string Automatic space insertion of functional style Automatic printing of standard containers, tuples, variants, optional Compile or run-time priority levels Compile or run-time sinks Constrained message length Support for wide-char streams Priority levels according to RFC-5424 section-6.2.1 2. Concerns The following conerns were identified Easy of use prevails of precise formatting A macro-free logger front-end is desirable, as macros: may trigger/expose unintended side-effects may hide build errors until a particular log-level is enabled discouraged by ISOCPP Allocation in the logger may induce bad alloc errors Unconstrained log message size accompanied with C++ operators may cause unintentionally huge data dumps Troubleshooting race conditions requires sync-free logging Log level limits should be available for build-time and run-time Sink selection should be available for build-time and run-time Logger tuning should be flexible enough to focus on a particular problem and void unrelated records Logger front-end should introduce minimal possible penalties and overhead Changing log level should not impact any possible side-effects of the user’s logging statements Logger’s formatter should not interfere with application’s formatters Access to the logger is needed from different contexts, such as static methods, free functions, lambdas. A shared instance of a logger front-end would require some synchronization technique In some use cases the log messages should be attributed with some common information, such as date, tag, source location, thread-id, process id. Some log sinks automatically attribute the messages, some others don’t In some cases log messages should be routed to more than one sink. This multi-sink routing may need some logic based on the message attributes Such sinks may have different approach or capabilities on message attributing Logger from-end is the on…

is_constexpr – a template to test if a function is constexpr
type: item
creator: Eugene
date: 2023-12-17T09:14:18Z
subject: C++
subject: constexpr
subject: SFINAE
description: C++ allows declaring functions as constexpr. Such functions could be evaluated at compile time and used, for example in if constexpr(...). However, a non-constexpr function in this context is not allowed. So, if we want to write a template, accepting a function and using it in either if constexpr(...) or old plain if(...) we need […]
encoded: C++ allows declaring functions as constexpr. Such functions could be evaluated at compile time and used, for example in if constexpr(...). However, a non-constexpr function in this context is not allowed. So, if we want to write a template, accepting a function and using it in either if constexpr(...) or old plain if(...) we need to test whether the function is constexpr, otherwise compile fails as illustrated below: template<auto F> bool is_zero() { if constexpr(F() == 0) { // error: constexpr if condition is not a constant expression return true; } else { return false; } } int notzero() { return 1; } constexpr int zero() { return 0; } bool test() { auto z1 = is_zero<notzero>(); // in instantiation of function template requested here auto z2 = is_zero<zero>(); return z1 || z2; } So we need to rewrite our is_zero as the following ... template<auto F> bool is_zero() { if constexpr(is_constexpr<F>::value) { if constexpr(F() == 0) { return true; } else return false; } else { return F() == 0; } } ... and implement is_constexpr using SFINAE: // is_constexpr.h template<auto F> struct constexpr_true : std::true_type {}; template<auto F> static auto test_constexpr(int) -> constexpr_true<F()>; template<auto F> static auto test_constexpr(long) -> std::false_type; template<auto F> struct is_constexpr : decltype(test_constexpr<F>(0)) {}; is_constexpr template has a constexpr member value, that can be used, for example in static_assert or if constexpr, as illustarted in the example below #include "is_constexpr.h" int notzero() { return 1; } constexpr int zero() { return 0; } static_assert(!is_constexpr<notzero>::value); static_assert(is_constexpr<zero>::value); template<auto F> bool is_zero() { if constexpr(is_constexpr<F>::value) { if constexpr(F() == 0) { return true; } else return false; } else { return F() == 0; } } bool test() { return is_zero<zero>() || is_zero<notzero>(); } Live is_constexpr example at godbolt.org

setof – an iterable set of strongly typed enumerations
type: item
creator: Eugene
date: 2020-01-02T07:47:53Z
subject: C++
subject: Research
subject: C++17
subject: class enum
subject: enum
subject: set
description: This post suggests an implementation of template class setof which facilitates features of a bit set and a forward-iterable container.
encoded: C++11 has introduced class enum - strongly scoped and strongly typed enumerations with class enum keywords. For example we may declare states of our FSA as the following: class enum state { shutdown, initialization, running, maintenance, finalization, }; However, using class enum to create masks is quite inconvenient: constexpr unsigned allowed = (1<<static_cast<int>(state::running)) | (1<<static_cast<int>(state::maintenance)) std::bitset does not help either on this matter. To address this case, a template class setof is suggested (also available on Gist setof.hpp) This class supports bitset type of operations & | &= |= set reset and facilitates an iterator over populated bits. #include <type_traits> #if __cplusplus > 201709L #include <bit> template<typename T> constexpr int countr_zero(T val) noexcept { return std::countr_zero(val); } template<typename T> constexpr int popcount(T val) noexcept { return std::popcount(val); } #else template<typename T, typename = std::enable_if_t<std::is_integral<T>::value,T>> constexpr int countr_zero(T val) noexcept { return __builtin_ctz(val); } template<typename T, typename = std::enable_if_t<std::is_integral<T>::value,T>> constexpr int popcount(T val) noexcept { return __builtin_popcount(val); } #endif template<typename T, typename = std::enable_if_t<std::is_integral<T>::value,T>> constexpr int bitwidth(const T&) noexcept { return sizeof(T) * 8; } template<template<std::size_t> class T, std::size_t N, typename = decltype(&T<N>::_Find_first)> constexpr int countr_zero(const T<N>& val) noexcept { return val._Find_first(); /* _Find_first is not in standard, its GCC extension */ } template<template<std::size_t> class T, std::size_t N> constexpr int popcount(const T<N>& val) noexcept { return val.count(); } template<template<std::size_t> class T, std::size_t N> constexpr int bitwidth(const T<N>& val) noexcept { return val.size(); } /** * setof - set of "named" bits, e.g. bit made from an enum * params: * Enum - enum type * Storage -…

C++ switch with textual cases
type: item
creator: Eugene
date: 2019-03-11T09:52:39Z
subject: C++
subject: C++17
description: C++ does not allow using string literals as case values in a switch statement. In modern C++ this restriction can be worked around with constexpr hash values. E.g. instead of using string literals, we will be using their hash codes, computed during compilation and matched agains a hash code of a varable string. First we […]
encoded: C++ does not allow using string literals as case values in a switch statement. In modern C++ this restriction can be worked around with constexpr hash values. E.g. instead of using string literals, we will be using their hash codes, computed during compilation and matched agains a hash code of a varable string. First we define a hash function: #pragma once #include <cstdint> #include <string_view> namespace fnv1b { /* FNV-1b hash function with extra rotation * https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function */ template<typename T = std::size_t> inline T hash(const char* str, std::size_t size) noexcept; template<typename T> inline constexpr T ror(T x, unsigned N) noexcept { return (x << (sizeof(T)*8 - N)) | ((x) >> (N)); } template<> inline constexpr uint32_t hash<uint32_t>(const char* str, std::size_t size) noexcept { constexpr uint32_t val32 = 0x811c9dc5; constexpr uint32_t prime32 = 16777619; uint32_t result = val32; while(size--) { result ^= uint32_t(*str); result = ror(result, (8+(0xF&(*str++)))); /* added rotation 8-23 bits */ result *= prime32; } return result; } template<> inline constexpr uint64_t hash<uint64_t>(const char* str, std::size_t size) noexcept { constexpr uint64_t val64 = 0xcbf29ce484222325; constexpr uint64_t prime64 = 1099511628211ULL; uint64_t result = val64; while(size--) { result ^= uint64_t(*str); result = ror(result, (8+(*str++)%48)); /* added rotation 8-55 bits */ result *= prime64; } return result; } template<typename T = std::size_t> inline constexpr T hash(const std::string_view str) noexcept { return hash<T>(str.data(), str.size()); } } Also available on gist For easy of use we define a literal operator, computing hash from a string literal: constexpr uint32_t operator "" _h(const char* str, size_t size) noexcept { return fnv1b::hash<uint32_t>(str, size); } Usage #include <iostream> #include <string> #include "hash_fnv1b.hpp" using namespace std; int main() { auto s = "hello"; switch(fnv1b::hash<uint32_t>(string_view(s))) {…

any_of<c1, …, c2>(v)
type: item
creator: Eugene
date: 2019-03-11T09:16:07Z
subject: C++
subject: C++17
description: This simple C++17 template implements constexpr any_of for matching a value against a list of constants. /** type_of_list<...>::type - helper structure for determining type of the first item in the list */ template<auto ... List> struct type_of_list; template<auto List> struct type_of_list<List> { using type = decltype(List); }; template<auto First, auto ... List > struct type_of_list<First, […]
encoded: This simple C++17 template implements constexpr any_of for matching a value against a list of constants. /** type_of_list<...>::type - helper structure for determining type of the first item in the list */ template<auto ... List> struct type_of_list; template<auto List> struct type_of_list<List> { using type = decltype(List); }; template<auto First, auto ... List > struct type_of_list<First, List...> : type_of_list<First> {}; /** type_of<...>::type - determines type of the first item in the list */ template<auto ... List> using type_of = typename type_of_list<List...>::type; /** any_of<...>(value) - compares value against all template parameters and returns true if any matches */ template<auto ... List> inline constexpr bool any_of(type_of<List...> value) noexcept { return ((value == List) || ...); } Also available on github as a gist any_of.hpp Usage #include <iostream> #include <string> enum class num { zero, one, two }; int main() { num v { num::one }; std::cout << any_of<num::zero, num::two>(v) << " " << any_of<num::zero, num::one>(v) << std::endl; } This example is also available on https://www.onlinegdb.com/BJLvFo7PN

COJSON library for Arduino
type: item
creator: Eugene
date: 2018-10-19T14:35:15Z
subject: cojson
subject: Arduino
subject: ARM
subject: ATmega
subject: avr
subject: C++
subject: Cortex-M0
subject: Cortex-M4
subject: embedded
subject: embedded systems
subject: json
subject: JSON for embedded systems
subject: json parser
subject: json serializer
subject: low end MCU
subject: MCU
description: COJSON library is also available as Arduino Studio .ZIP library: cojson.zip. To add the library to your sketch, download cojson.zip, select: Sketch > Include Library > Add .ZIP Library ... The library sources are available in a separate repository on github: cojson.lib
encoded: COJSON library is also available as Arduino Studio .ZIP library: cojson.zip. To add the library to your sketch, download cojson.zip, select: Sketch > Include Library > Add .ZIP Library ... The library sources are available in a separate repository on github: cojson.lib

cojson tutorial for C++17
type: item
creator: Eugene
date: 2018-10-15T07:59:10Z
subject: cojson
subject: C++17
subject: embedded
subject: embedded systems
subject: json
subject: JSON for embedded systems
subject: json parser
subject: json serializer
subject: MCU
description: C++17 has simplified use of template parameters. Instructions, given in this tutorial, describes how to define JSON model with cojson::autos templates. Note: GCC 7 or higher is required to compile cojson_autos.hpp ! 1. Defining Model JSON model is defined as a template function, with pointers to all serializable members as the template parameters. Everything else […]
encoded: C++17 has simplified use of template parameters. Instructions, given in this tutorial, describes how to define JSON model with cojson::autos templates. Note: GCC 7 or higher is required to compile cojson_autos.hpp ! 1. Defining Model JSON model is defined as a template function, with pointers to all serializable members as the template parameters. Everything else - JSON property name, data type, array extents, is deduced from pointer-to-member by cojson::autos templates. cojson::autos defines two groups of template functions each having its specific purpose and name: O<class,...>() Object<class, ...>() Defines an object mapped to a C++ class P<auto,auto>() Property<auto,auto>() Defines an object property, bound to getter/setter or to an inner object struct MyClass { int Int; } obj; O<MyClass,&MyClass::Int>().read(obj, in); 1.1. Objects Class-bound objects are defined with variadic template O<...> that accepts bounding class as the first parameter followed by the list of member pointers, method pointers or P templates. 1.2. Names cojson::autos templates deduce names from the identifiers. E.g. member Int will be mapped to JSON property "Int". In a case, when this approach is not suitable, a cojson::P template should be used to define a property with an alternate name. 2. Scalar properties 2.1. Members A class's member is referred by its pointer to member, e.g. &MyClass::Int 2.2. Methods A property, mapped to a single getter or setter is referred by its pointer to method, e.g. &MyClass::setLatch. A property, that needs two methods - getter and setter, is defined by cojson::autos::P template, e.g. P<&MyClass::getLatch, &MyClass::setLatch>. 2.3. Immutable String Immutable zero-terminated strings of unspecified length can be provided: by a pointer to (const) member of const char* by a pointer to method returning const char* by template PropertyStaticString with the class and a pointer to static member of const char* by template PropertyFunctionString with the class and a …