Skip to content

Patternia v0.6.0 Release Note

Release Date: December 16, 2025 Version: 0.6.0


Overview

Patternia v0.6.0 represents a significant advancement in pattern matching capabilities, introducing generic lambda support, multi-value guard expressions, structural binding enhancements, and strongly-typed evaluation mechanisms. This release enhances the expressiveness and type safety of pattern matching while maintaining zero-overhead performance guarantees.


New Features

Generic Lambda Support for Pattern Matching

Added: Full support for generic lambdas in pattern matching handlers through template operator() detection.

// Generic lambda with auto parameters
match(container)
    .when(bind(has<&Container::elements>()) >> [](auto&& elems) {
        return process_generic_elements(elems);
    })
    .otherwise([] { return handle_empty(); });

// Generic lambda with multiple parameters
match(data)
    .when(bind(has<&Data::value, &Data::type>()) >> [](auto val, auto&& type) {
        return handle_generic_data(val, type);
    })
    .otherwise([] { return default_handler(); });

Technical Implementation: - Template operator() detection for 1-4 parameter arities - Forward reference support for perfect forwarding - Type deduction improvements for generic handlers - Seamless integration with existing pattern infrastructure

Multi-Value Guard Expressions with arg Placeholders

Enhanced: Advanced guard system supporting relationships between multiple bound values.

// Multi-value comparisons using arg<N> placeholders
match(point)
    .when(bind(has<&Point::x, &Point::y>())[arg<0> + arg<1> == 0] >> 
         [](int x, int y) { return "on diagonal"; })
    .when(bind(has<&Point::x, &Point::y>())[arg<0> * arg<1] > 100] >>
         [](int x, int y) { return "large product"; })
    .otherwise([] { return "other"; });

// Complex multi-value conditions
match(rectangle)
    .when(bind(has<&Rect::width, &Rect::height>())
          [arg<0> > arg<1> && arg<0> + arg<1> < 100] >>
         [](int width, int height) { return "wide, small perimeter"; })
    .when(bind(has<&Rect::width, &Rect::height>())
          [arg<0> == arg<1>] >>
         [](int width, int height) { return "square"; })
    .otherwise([] { return "other"; });

Guard Expression Features: - arg<N> placeholders for accessing Nth bound value - Binary operations between different bound values - Complex logical combinations with && and || - Type-safe compile-time validation of guard expressions - Support for arithmetic, comparison, and logical operations

Structural Binding for has_pattern

Enhanced: Direct binding of member fields when using bind() with structural patterns.

struct Point { int x, y; };
struct Circle { Point center; int radius; };

// Direct field binding from structural patterns
match(point)
    .when(bind(has<&Point::x, &Point::y>()) >> [](int x, int y) {
        return fmt::format("point: ({}, {})", x, y);
    })
    .otherwise([] { return "invalid point"; });

// Nested structural binding
match(circle)
    .when(bind(has<&Circle::center, &Circle::radius>()) >> 
         [](const Point& center, int radius) {
        return fmt::format("circle: center({},{}), radius={}", 
                           center.x, center.y, radius);
    })
    .otherwise([] { return "invalid circle"; });

// Mixed structural and wildcard binding
shape = std::variant<Point, Circle>{};
match(shape)
    .when(bind(has<&Point::x, &Point::y>()) >> [](int x, int y) {
        return fmt::format("point: ({}, {})", x, y);
    })
    .otherwise([] { return "unknown shape"; });

Structural Binding Capabilities: - Automatic tuple generation from member pointers - Type preservation for reference and const semantics - Integration with wildcard patterns for partial binding - Compile-time validation of member accessibility - Zero-overhead field extraction

Strongly-Typed Evaluation System

Added: Comprehensive type safety and evaluation framework for pattern matching.

// Type-safe evaluation with compile-time guarantees
match(value)
    .when(bind() >> [](auto&& val) requires std::integral<decltype(val)> {
        return process_integral(val);
    })
    .when(bind() >> [](auto&& val) requires std::floating_point<decltype(val)> {
        return process_floating(val);
    })
    .otherwise([] { return handle_unknown_type(); });

// Strongly-typed guard evaluation
match(data)
    .when(bind()[[](auto x) { return std::is_arithmetic_v<decltype(x)>; }] >>
         [](auto&& x) { return process_arithmetic(x); })
    .otherwise([] { return handle_non_arithmetic(); });

Type System Features: - Compile-time type validation for pattern contracts - Type-safe guard predicate evaluation - Template constraint integration with C++20 concepts - Enhanced type deduction for complex patterns - Improved error messages for type mismatches


Internal Improvements

Enhanced Type Traits System

Expanded: Comprehensive type detection and validation capabilities.

// Generic lambda detection improvements
template<typename T>
concept is_generic_lambda = requires(T t) {
    requires requires { t.operator()(auto{}); } ||
              requires { t.operator()(auto{}, auto{}); } ||
              requires { t.operator()(auto{}, auto{}, auto{}); } ||
              requires { t.operator()(auto{}, auto{}, auto{}, auto{}); };
};

// Multi-value guard expression type validation
template<typename... Args>
concept valid_guard_expression = requires(Args... args) {
    requires (sizeof...(Args) <= 4);
    requires (std::conjunction_v<std::is_invocable<Args>...>);
};

Builder Framework Enhancements

Improved: Advanced pattern matching infrastructure with better type safety.

  • Enhanced builder implementation for generic lambda support
  • Improved type deduction for complex pattern compositions
  • Better error handling and validation in pattern construction
  • Optimized template instantiation for faster compilation

Performance Optimizations

Maintained: Zero-overhead guarantees with enhanced optimization opportunities.

  • Compile-time evaluation of guard expressions where possible
  • Improved inlining for generic lambda handlers
  • Optimized tuple generation for structural binding
  • Enhanced template metaprogramming for type deduction

Architecture Changes

Multi-Value Guard Architecture

Added: Comprehensive framework for complex guard expressions.

// arg<N> placeholder system
template<std::size_t N>
struct arg_placeholder {
    template<typename... Args>
    constexpr auto operator()(Args&&... args) const -> decltype(auto) {
        return std::get<N>(std::forward_as_tuple(args...));
    }
};

// Binary operation support for guard expressions
template<typename LHS, typename Op, typename RHS>
struct binary_guard_expression {
    LHS lhs;
    RHS rhs;

    template<typename... Args>
    constexpr auto operator()(Args&&... args) const -> decltype(auto) {
        return Op{}(lhs(args...), rhs(args...));
    }
};

Structural Binding Framework

Enhanced: Advanced member pointer-based binding system.

// Structural bind pattern implementation
template<typename... MemberPtrs>
struct structural_bind_pattern {
    template<typename Subject>
    constexpr auto match(Subject&& subject) const {
        return std::tuple<member_type_t<MemberPtrs>...>{
            subject.*MemberPtrs...
        };
    }
};

Generic Lambda Handler System

Added: Template operator() detection and invocation framework.

// Generic lambda detection and arity determination
template<typename T, typename = void>
struct is_generic_lambda : std::false_type {};

template<typename T>
struct is_generic_lambda<T, std::void_t<decltype(&T::template operator()<auto>)>> 
    : std::true_type {};

Usage Examples

Generic Lambda with Structural Binding

struct Matrix { int rows, cols; std::vector<double> data; };

match(matrix)
    .when(bind(has<&Matrix::rows, &Matrix::cols, &Matrix::data>()) >>
         [](auto rows, auto&& cols, auto&& data) requires std::ranges::range<decltype(data)> {
        return fmt::format("matrix: {}x{} with {} elements", rows, cols, data.size());
    })
    .otherwise([] { return "invalid matrix"; });

Multi-Value Guard with Complex Logic

struct Triangle { int a, b, c; };

match(triangle)
    .when(bind(has<&Triangle::a, &Triangle::b, &Triangle::c>())
          [arg<0> + arg<1] > arg<2> && 
           arg<1] + arg<2] > arg<0> && 
           arg<0] + arg<2] > arg<1]] >>
         [](int a, int b, int c) { return "valid triangle"; })
    .when(bind(has<&Triangle::a, &Triangle::b, &Triangle::c>())
          [arg<0] == arg<1] && arg<1] == arg<2]] >>
         [](int a, int b, int c) { return "equilateral triangle"; })
    .otherwise([] { return "invalid triangle"; });

Advanced Generic Lambda Processing

template<typename Container>
auto process_container(const Container& container) {
    return match(container)
        .when(bind(has<&Container::size, &Container::data>()) >>
             [](auto size, auto&& data) requires std::ranges::range<decltype(data)> {
                return fmt::format("container with {} elements", size);
             })
        .when(bind() >> [](auto&& c) requires requires { c.size(); } {
                return fmt::format("sized container: {}", c.size());
             })
        .when(bind() >> [](auto&& c) requires std::ranges::range<decltype(c)> {
                return fmt::format("range container");
             })
        .otherwise([] { return "unknown container type"; });
}

Complex Pattern Composition

struct NetworkPacket {
    uint16_t source_port;
    uint16_t dest_port;
    uint32_t sequence;
    std::vector<uint8_t> payload;
};

match(packet)
    .when(bind(has<&NetworkPacket::source_port, &NetworkPacket::dest_port,
                &NetworkPacket::sequence, &NetworkPacket::payload>())
          [arg<0] != arg<1> && arg<2] > 0] >>
         [](uint16_t src, uint16_t dst, uint32_t seq, auto&& payload) {
            return fmt::format("packet: {}->{} (seq: {}, payload: {} bytes)", 
                              src, dst, seq, payload.size());
         })
    .when(bind(has<&NetworkPacket::source_port, &NetworkPacket::dest_port>())
          [arg<0] == arg<1]] >>
         [](uint16_t port, uint16_t) {
            return fmt::format("loopback packet on port {}", port);
         })
    .otherwise([] { return "malformed packet"; });

Documentation Improvements

Enhanced API Reference

Updated: Comprehensive documentation covering new features: - Generic lambda handler documentation - Multi-value guard expression reference - Structural binding usage patterns - Type system improvements documentation

Expanded Sample Code

Added: New and improved sample implementations: - samples/fibo.cpp - Generic lambda with guard expressions - samples/handle_packet.cpp - Complex protocol parsing with structural binding - Improved code comments and inline documentation

README Enhancements

Expanded: Comprehensive quick start and reference documentation: - Patternia benefits explanation - Advanced usage patterns - Performance characteristics - Type safety guarantees


Bug Fixes

Template Compilation Issues

Resolved: Advanced template compilation problems: - Generic lambda operator() detection edge cases - Multi-value guard expression instantiation failures - Structural binding type deduction problems - Template argument deduction for complex patterns

Type System Validation

Fixed: Type safety and validation issues: - Guard predicate type resolution for generic expressions - Binding contract forwarding for nested patterns - Member pointer accessibility validation in structural patterns - Type preservation in generic lambda handlers

Performance Edge Cases

Resolved: Optimization and performance issues: - Template instantiation overhead for complex patterns - Unnecessary tuple copying in structural binding - Guard expression evaluation optimization - Generic lambda inlining improvements


Migration Guide

From v0.5.x to v0.6.0

Generic Lambda Support:

// v0.5.x - Required explicit types
.when(bind() >> [](int x) { return process(x); })

// v0.6.0 - Supports generic lambdas
.when(bind() >> [](auto&& x) { return process(x); })

Multi-Value Guards:

// v0.5.x - Limited to single-value guards
.when(bind()[_ > 0] >> handler)

// v0.6.0 - Multi-value relationship support
.when(bind(has<&Point::x, &Point::y>())[arg<0] + arg<1] == 0] >> handler)

Structural Binding:

// v0.5.x - Manual field access
.when(has<&Point::x, &Point::y>() >> bind() >> [](auto&& p) {
    return process(p.x, p.y);
})

// v0.6.0 - Direct field binding
.when(bind(has<&Point::x, &Point::y>()) >> [](int x, int y) {
    return process(x, y);
})


Performance Impact

Compilation Time: Slight increase due to enhanced template metaprogramming Runtime Performance: No performance degradation, maintains zero-overhead guarantees Binary Size: Minimal increase from template instantiation overhead Type Safety: Significant improvement in compile-time error detection


Future Compatibility

This release maintains full backward compatibility with v0.5.x code while introducing new capabilities. All existing pattern matching constructs continue to work without modification. New features are additive and do not change the behavior of existing patterns.