JH-Toolkit v1.4.1
An engineering-oriented C++20 toolkit with duck-typed concepts, static design, async coroutines, and semantic containers — header-only, RTTI-free, and concurrency-friendly.
Loading...
Searching...
No Matches
variant_adt.h File Reference

ADT utilities for std::variant — compile-time checks and transformations. More...

#include <cstddef>
#include <variant>

Go to the source code of this file.

Namespaces

namespace  jh::meta
 Aggregated entry point for compile-time metaprogramming utilities.

Concepts

concept  jh::meta::check_all
 Compile-time predicate applied to all alternatives in a variant.

Typedefs

template<std::size_t I, typename Variant, template< typename > typename TpTrans>
using jh::meta::deduce_type_t = typename detail::deduce_type<I, Variant, TpTrans>::type
 Extracts the transformed type of the I-th alternative in a variant.
template<typename Variant, template< typename > typename TpTrans>
using jh::meta::variant_transform_t = typename detail::variant_transform_impl<Variant, TpTrans>::type
 Applies a unary type transformation to every alternative in a variant.
template<typename Variant, template< typename > typename TpTrans>
using jh::meta::variant_collapse_t
 Attempts to collapse a transformed variant into a single uniform type.

Detailed Description

ADT utilities for std::variant — compile-time checks and transformations.

Author
JeongHan-Bae <mastropseudo@gmail.com>

Design Goals

Abstract Data Type (ADT) is better than inheriting.
MCPP Philosophy: Composition over inheritance, separating data from objects.

About using std::variant as a closed, memory-friendly alternative to inheritance:

  1. Memory locality & predictable storage
  2. Closed set of types (closed world assumption)
  3. No vtable / no RTTI dependency
  4. A modern and safer C++20 pattern

The ADT-based checking framework leverages these benefits by providing a generic way to apply compile-time conditions to every type inside a std::variant.

Design Notes

A type-transform applied to a variant must produce either:

  • a uniform result type for all alternatives (e.g., a hash → size_t), in which case the variant can be collapsed to a single type
  • a set of pairwise distinct result types, in which case the variant can be transformed into another variant

Mixed outcomes (some alternatives mapping to identical types while others do not) are considered invalid in real-world business models. Such a design indicates inconsistent semantics and should be rejected by static checks (e.g. via check_all). Sometimes you might need mappings like:

A  -> TA;
BA -> TB;
BB -> TB;
BC -> TB;
C  -> TC;
D  -> TD;

But note that BA, BB, and BC are actually of the same family from the outermost perspective. You should use std::variant<A, std::variant<BA, BB, BC>, C, D> instead of std::variant<A, BA, BB, BC, C, D>. Here we actually notice that the outer layer is ALL-to-ALL inflexion, but family B undergoes collapse.

This can be easily achieved using using VB = std::variant<BA, BB, BC> and then applying variant_collapse_t<VB, your_transform> inside the outer variant transform Transformer<VB>{...} , (aligned withTransformer, Transformer<C>, Transformer<D>).

Version
1.4.x
Date
2025