Skip to content
Merged
13 changes: 13 additions & 0 deletions examples/ex01_default_arithmetic.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/*
* Example: ex01_default_arithmetic
*
* Purpose:
* Demonstrate the default primitive aliases and operator pipeline for
* arithmetic operations without custom policy overrides.
*
* Expected results:
* - All four operations (+, -, *, /) succeed through dispatcher.
* - The printed values match: sum=42, diff=38, prod=80, quot=20.
* - Program exits with code 0; otherwise prints an error and exits non-zero.
*/

#include <cstdint>
#include <iostream>

Expand Down
14 changes: 14 additions & 0 deletions examples/ex02_type_policy.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
/*
* Example: ex02_type_policy
*
* Purpose:
* Compare type negotiation behavior between strict and compatible policies.
*
* Expected results:
* - strict policy rejects mixed reps (int + long long) at compile-time
* negotiation, yielding common_rep=void.
* - compatible policy accepts mixed arithmetic reps and negotiates
* common_rep=long long.
* - Program prints a success message and exits with code 0.
*/

#include <iostream>
#include <type_traits>

Expand Down
14 changes: 14 additions & 0 deletions examples/ex03_value_policy.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
/*
* Example: ex03_value_policy
*
* Purpose:
* Show how checked, unchecked, and saturating value policies behave under
* the same overflow input.
*
* Expected results:
* - checked: reports overflow as an error.
* - unchecked: wraps according to native arithmetic semantics.
* - saturating: clamps to the representable upper bound.
* - Program prints observed values and exits with code 0.
*/

#include <cstdint>
#include <iostream>

Expand Down
12 changes: 12 additions & 0 deletions examples/ex04_error_policy.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
/*
* Example: ex04_error_policy
*
* Purpose:
* Compare error handling styles (expected vs throwing) under divide-by-zero.
*
* Expected results:
* - expected policy returns error::kind::divide_by_zero.
* - throwing policy throws std::runtime_error.
* - Program validates both paths and exits with code 0.
*/

#include <iostream>
#include <stdexcept>

Expand Down
13 changes: 13 additions & 0 deletions examples/ex05_concurrency_policy.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/*
* Example: ex05_concurrency_policy
*
* Purpose:
* Demonstrate the atomic concurrency policy path under multi-threaded
* repeated dispatch.
*
* Expected results:
* - Concurrent add operations consistently produce value 42.
* - mismatch_count remains zero after all worker threads join.
* - Program prints a success message and exits with code 0.
*/

#include <atomic>
#include <iostream>
#include <thread>
Expand Down
209 changes: 209 additions & 0 deletions examples/ex06_custom_underlying.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
/*
* Example: ex06_custom_underlying
*
* Purpose:
* Demonstrate custom underlying integration, including rep bridge,
* rep validation, and extensible common_rep negotiation.
*
* Expected results:
* - UserInteger path succeeds and computes 40 + 2 = 42.
* - NonNegativeInt path rejects invalid rep and returns domain_error.
* - TaggedLhs/TaggedRhs path uses custom common_rep_traits to negotiate
* TaggedCommonRep, then computes 40 + 2 = 42.
* - Program prints a success message and exits with code 0.
*/

#include <iostream>
#include <type_traits>

import mcpplibs.primitives;

Expand All @@ -13,6 +29,110 @@ struct NonNegativeInt {
int value;
};

struct TaggedLhs {
int value;

friend constexpr auto operator+(TaggedLhs lhs, TaggedLhs rhs) noexcept
-> TaggedLhs {
return TaggedLhs{lhs.value + rhs.value};
}

friend constexpr auto operator-(TaggedLhs lhs, TaggedLhs rhs) noexcept
-> TaggedLhs {
return TaggedLhs{lhs.value - rhs.value};
}

friend constexpr auto operator*(TaggedLhs lhs, TaggedLhs rhs) noexcept
-> TaggedLhs {
return TaggedLhs{lhs.value * rhs.value};
}

friend constexpr auto operator/(TaggedLhs lhs, TaggedLhs rhs) noexcept
-> TaggedLhs {
return TaggedLhs{lhs.value / rhs.value};
}

friend constexpr auto operator==(TaggedLhs lhs, TaggedLhs rhs) noexcept
-> bool {
return lhs.value == rhs.value;
}

constexpr explicit operator long long() const noexcept {
return static_cast<long long>(value);
}
};

struct TaggedRhs {
int value;

friend constexpr auto operator+(TaggedRhs lhs, TaggedRhs rhs) noexcept
-> TaggedRhs {
return TaggedRhs{lhs.value + rhs.value};
}

friend constexpr auto operator-(TaggedRhs lhs, TaggedRhs rhs) noexcept
-> TaggedRhs {
return TaggedRhs{lhs.value - rhs.value};
}

friend constexpr auto operator*(TaggedRhs lhs, TaggedRhs rhs) noexcept
-> TaggedRhs {
return TaggedRhs{lhs.value * rhs.value};
}

friend constexpr auto operator/(TaggedRhs lhs, TaggedRhs rhs) noexcept
-> TaggedRhs {
return TaggedRhs{lhs.value / rhs.value};
}

friend constexpr auto operator==(TaggedRhs lhs, TaggedRhs rhs) noexcept
-> bool {
return lhs.value == rhs.value;
}

constexpr explicit operator long long() const noexcept {
return static_cast<long long>(value);
}
};

struct TaggedCommonRep {
long long value;

constexpr TaggedCommonRep() noexcept = default;
constexpr explicit TaggedCommonRep(long long v) noexcept : value(v) {}
constexpr explicit TaggedCommonRep(TaggedLhs v) noexcept : value(v.value) {}
constexpr explicit TaggedCommonRep(TaggedRhs v) noexcept : value(v.value) {}

friend constexpr auto operator+(TaggedCommonRep lhs,
TaggedCommonRep rhs) noexcept
-> TaggedCommonRep {
return TaggedCommonRep{lhs.value + rhs.value};
}

friend constexpr auto operator-(TaggedCommonRep lhs,
TaggedCommonRep rhs) noexcept
-> TaggedCommonRep {
return TaggedCommonRep{lhs.value - rhs.value};
}

friend constexpr auto operator*(TaggedCommonRep lhs,
TaggedCommonRep rhs) noexcept
-> TaggedCommonRep {
return TaggedCommonRep{lhs.value * rhs.value};
}

friend constexpr auto operator/(TaggedCommonRep lhs,
TaggedCommonRep rhs) noexcept
-> TaggedCommonRep {
return TaggedCommonRep{lhs.value / rhs.value};
}

friend constexpr auto operator==(TaggedCommonRep lhs,
TaggedCommonRep rhs) noexcept -> bool {
return lhs.value == rhs.value;
}
};

// Point 6 / Step 2: Register underlying::traits for UserInteger.
// This type has a full int bridge and accepts all reps.
template <> struct mcpplibs::primitives::underlying::traits<UserInteger> {
Expand Down Expand Up @@ -55,6 +175,74 @@ template <> struct mcpplibs::primitives::underlying::traits<NonNegativeInt> {
}
};

template <> struct mcpplibs::primitives::underlying::traits<TaggedLhs> {
using value_type = TaggedLhs;
using rep_type = TaggedLhs;

static constexpr bool enabled = true;
static constexpr auto kind = category::integer;

static constexpr auto to_rep(value_type value) noexcept -> rep_type {
return value;
}

static constexpr auto from_rep(rep_type value) noexcept -> value_type {
return value;
}

static constexpr auto is_valid_rep(rep_type) noexcept -> bool { return true; }
};

template <> struct mcpplibs::primitives::underlying::traits<TaggedRhs> {
using value_type = TaggedRhs;
using rep_type = TaggedRhs;

static constexpr bool enabled = true;
static constexpr auto kind = category::integer;

static constexpr auto to_rep(value_type value) noexcept -> rep_type {
return value;
}

static constexpr auto from_rep(rep_type value) noexcept -> value_type {
return value;
}

static constexpr auto is_valid_rep(rep_type) noexcept -> bool { return true; }
};

template <> struct mcpplibs::primitives::underlying::traits<TaggedCommonRep> {
using value_type = TaggedCommonRep;
using rep_type = TaggedCommonRep;

static constexpr bool enabled = true;
static constexpr auto kind = category::integer;

static constexpr auto to_rep(value_type value) noexcept -> rep_type {
return value;
}

static constexpr auto from_rep(rep_type value) noexcept -> value_type {
return value;
}

static constexpr auto is_valid_rep(rep_type) noexcept -> bool { return true; }
};

template <>
struct mcpplibs::primitives::underlying::common_rep_traits<TaggedLhs,
TaggedRhs> {
using type = TaggedCommonRep;
static constexpr bool enabled = true;
};

template <>
struct mcpplibs::primitives::underlying::common_rep_traits<TaggedRhs,
TaggedLhs> {
using type = TaggedCommonRep;
static constexpr bool enabled = true;
};

int main() {
// Point 6 / Step 4A: Call operations on UserInteger custom underlying.
using user_t =
Expand All @@ -81,6 +269,27 @@ int main() {
return 1;
}

// Point 6 / Step 4C: Demonstrate extensible common_rep negotiation.
using lhs_t = primitive<TaggedLhs, policy::value::checked,
policy::type::transparent, policy::error::expected>;
using rhs_t = primitive<TaggedRhs, policy::value::checked,
policy::type::transparent, policy::error::expected>;

using transparent_handler =
policy::type::handler<policy::type::transparent, operations::Addition,
TaggedLhs, TaggedRhs>;
static_assert(transparent_handler::allowed);
static_assert(
std::same_as<typename transparent_handler::common_rep, TaggedCommonRep>);

auto const lhs = lhs_t{TaggedLhs{40}};
auto const rhs = rhs_t{TaggedRhs{2}};
auto const mixed_result = operations::add(lhs, rhs);
if (!mixed_result.has_value() || mixed_result->value().value != 42) {
std::cerr << "custom common_rep negotiation failed\n";
return 1;
}

std::cout << "custom underlying demo passed\n";
return 0;
}
14 changes: 14 additions & 0 deletions examples/ex07_custom_policy.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
/*
* Example: ex07_custom_policy
*
* Purpose:
* Show end-to-end customization of all policy dimensions (type, value,
* error, concurrency) and custom operation binding integration.
*
* Expected results:
* - Custom policy traits are recognized and selected by dispatcher.
* - Custom value finalize step adjusts addition result by +1.
* - Input 20 and 21 produces final value 42.
* - Program prints a success message and exits with code 0.
*/

#include <expected>
#include <iostream>
#include <type_traits>
Expand Down
13 changes: 13 additions & 0 deletions examples/ex08_custom_operation.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/*
* Example: ex08_custom_operation
*
* Purpose:
* Demonstrate how to register new operation tags, declare operation traits,
* and provide runtime op_binding specializations.
*
* Expected results:
* - Custom operations Average, GreaterThan, and BitAnd dispatch successfully.
* - For inputs 10 and 6, outputs are avg=8, gt=1, bitand=2.
* - Program prints computed values and exits with code 0.
*/

#include <iostream>

import mcpplibs.primitives;
Expand Down
10 changes: 7 additions & 3 deletions src/policy/impl.cppm
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module;
#include <string>
#include <concepts>
#include <exception>
#include <expected>
#include <stdexcept>
#include <string>
#include <type_traits>


export module mcpplibs.primitives.policy.impl;

import mcpplibs.primitives.operations.traits;
Expand Down Expand Up @@ -149,6 +150,7 @@ struct type::handler<type::compatible, OpTag, LhsRep, RhsRep> {
static constexpr bool enabled = true;
static constexpr bool allowed =
std::is_arithmetic_v<LhsRep> && std::is_arithmetic_v<RhsRep> &&
has_common_rep<LhsRep, RhsRep> &&
!details::rejects_arithmetic_for_boolean_or_character_v<OpTag, LhsRep,
RhsRep>;
static constexpr unsigned diagnostic_id =
Expand All @@ -157,17 +159,19 @@ struct type::handler<type::compatible, OpTag, LhsRep, RhsRep> {
? 3u
: (allowed ? 0u : 2u);
using common_rep =
std::conditional_t<allowed, std::common_type_t<LhsRep, RhsRep>, void>;
std::conditional_t<allowed, common_rep_t<LhsRep, RhsRep>, void>;
};

template <operations::operation OpTag, typename LhsRep, typename RhsRep>
struct type::handler<type::transparent, OpTag, LhsRep, RhsRep> {
static constexpr bool enabled = true;
static constexpr bool allowed =
has_common_rep<LhsRep, RhsRep> &&
!details::rejects_arithmetic_for_boolean_or_character_v<OpTag, LhsRep,
RhsRep>;
static constexpr unsigned diagnostic_id = allowed ? 0u : 3u;
using common_rep = std::common_type_t<LhsRep, RhsRep>;
using common_rep =
std::conditional_t<allowed, common_rep_t<LhsRep, RhsRep>, void>;
};

template <operations::operation OpTag, typename CommonRep,
Expand Down
Loading
Loading