#include <iostream>
#include "static-calculator.hpp"
int main() {
// Test basic arithmetic operations
using addition_expr = typename_array<value_wrapper<'1'>, value_wrapper<'+'>, value_wrapper<'2'>>;
static_assert(addition_expr::template acquire<static_calculator>::result == 3,
"Test failed: Basic addition should evaluate to 3");
std::cout << "Basic addition (1+2): " << addition_expr::template acquire<static_calculator>::result << std::endl;
using subtraction_expr = typename_array<value_wrapper<'5'>, value_wrapper<'-'>, value_wrapper<'2'>>;
static_assert(subtraction_expr::template acquire<static_calculator>::result == 3,
"Test failed: Basic subtraction should evaluate to 3");
std::cout << "Basic subtraction (5-2): " << subtraction_expr::template acquire<static_calculator>::result << std::endl;
using multiplication_expr = typename_array<value_wrapper<'3'>, value_wrapper<'*'>, value_wrapper<'4'>>;
static_assert(multiplication_expr::template acquire<static_calculator>::result == 12,
"Test failed: Basic multiplication should evaluate to 12");
std::cout << "Basic multiplication (3*4): " << multiplication_expr::template acquire<static_calculator>::result << std::endl;
using division_expr = typename_array<value_wrapper<'8'>, value_wrapper<'/'>, value_wrapper<'2'>>;
static_assert(division_expr::template acquire<static_calculator>::result == 4,
"Test failed: Basic division should evaluate to 4");
std::cout << "Basic division (8/2): " << division_expr::template acquire<static_calculator>::result << std::endl;
using modulo_expr = typename_array<value_wrapper<'7'>, value_wrapper<'%'>, value_wrapper<'3'>>;
static_assert(modulo_expr::template acquire<static_calculator>::result == 1,
"Test failed: Basic modulo should evaluate to 1");
std::cout << "Basic modulo (7%3): " << modulo_expr::template acquire<static_calculator>::result << std::endl;
// Test order of operations
using order_expr1 = typename_array<value_wrapper<'2'>, value_wrapper<'+'>, value_wrapper<'3'>, value_wrapper<'*'>, value_wrapper<'4'>>;
static_assert(order_expr1::template acquire<static_calculator>::result == 14,
"Test failed: Expression with proper order of operations should evaluate to 14");
std::cout << "Order of operations (2+3*4): " << order_expr1::template acquire<static_calculator>::result << std::endl;
using order_expr2 = typename_array<value_wrapper<'8'>, value_wrapper<'/'>, value_wrapper<'4'>, value_wrapper<'+'>, value_wrapper<'3'>>;
static_assert(order_expr2::template acquire<static_calculator>::result == 5,
"Test failed: Division and addition should evaluate to 5");
std::cout << "Division and addition (8/4+3): " << order_expr2::template acquire<static_calculator>::result << std::endl;
// Test parentheses
using paren_expr1 = typename_array<value_wrapper<'('>, value_wrapper<'2'>, value_wrapper<'+'>, value_wrapper<'3'>, value_wrapper<')'>, value_wrapper<'*'>, value_wrapper<'4'>>;
static_assert(paren_expr1::template acquire<static_calculator>::result == 20,
"Test failed: Expression with parentheses should evaluate to 20");
std::cout << "Expression with parentheses ((2+3)*4): " << paren_expr1::template acquire<static_calculator>::result << std::endl;
using paren_expr2 = typename_array<value_wrapper<'2'>, value_wrapper<'*'>, value_wrapper<'('>, value_wrapper<'3'>, value_wrapper<'+'>, value_wrapper<'4'>, value_wrapper<')'>>;
static_assert(paren_expr2::template acquire<static_calculator>::result == 14,
"Test failed: Expression with parentheses should evaluate to 14");
std::cout << "Expression with parentheses (2*(3+4)): " << paren_expr2::template acquire<static_calculator>::result << std::endl;
// Test multi-digit numbers
using multi_digit_expr = typename_array<value_wrapper<'1'>, value_wrapper<'2'>, value_wrapper<'3'>, value_wrapper<'+'>, value_wrapper<'4'>, value_wrapper<'5'>, value_wrapper<'6'>>;
static_assert(multi_digit_expr::template acquire<static_calculator>::result == 579,
"Test failed: Expression with multi-digit numbers should evaluate to 579");
std::cout << "Multi-digit numbers (123+456): " << multi_digit_expr::template acquire<static_calculator>::result << std::endl;
// Test complex expressions
using complex_expr1 = typename_array<value_wrapper<'2'>, value_wrapper<'*'>, value_wrapper<'('>, value_wrapper<'3'>, value_wrapper<'+'>, value_wrapper<'4'>, value_wrapper<')'>, value_wrapper<'-'>, value_wrapper<'5'>, value_wrapper<'/'>, value_wrapper<'2'>>;
static_assert(complex_expr1::template acquire<static_calculator>::result == 12,
"Test failed: Complex expression should evaluate to 12");
std::cout << "Complex expression (2*(3+4)-5/2): " << complex_expr1::template acquire<static_calculator>::result << std::endl;
using complex_expr2 = typename_array<value_wrapper<'('>, value_wrapper<'1'>, value_wrapper<'0'>, value_wrapper<'+'>, value_wrapper<'5'>, value_wrapper<'*'>, value_wrapper<'2'>, value_wrapper<')'>, value_wrapper<'/'>, value_wrapper<'('>, value_wrapper<'4'>, value_wrapper<'-'>, value_wrapper<'2'>, value_wrapper<')'>>;
static_assert(complex_expr2::template acquire<static_calculator>::result == 10,
"Test failed: Complex expression with nested parentheses should evaluate to 10");
std::cout << "Complex expression with nested parentheses ((10+5*2)/(4-2)): " << complex_expr2::template acquire<static_calculator>::result << std::endl;
// Test multiple nested parentheses
using nested_paren_expr = typename_array<
value_wrapper<'('>, value_wrapper<'1'>, value_wrapper<'+'>,
value_wrapper<'('>, value_wrapper<'('>, value_wrapper<'2'>, value_wrapper<'+'>, value_wrapper<'3'>, value_wrapper<')'>,
value_wrapper<'*'>,
value_wrapper<'('>, value_wrapper<'4'>, value_wrapper<'+'>, value_wrapper<'5'>, value_wrapper<')'>, value_wrapper<')'>,
value_wrapper<')'>
>;
static_assert(nested_paren_expr::template acquire<static_calculator>::result == 46,
"Test failed: Expression with multiple nested parentheses should evaluate to 46");
std::cout << "Multiple nested parentheses (1+((2+3)*(4+5))): " << nested_paren_expr::template acquire<static_calculator>::result << std::endl;
return 0;
}
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_APPLY_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_APPLY_H
#include "base.hpp"
/// <summary>
/// Applies a function template to each type in an array, producing a new array with transformed types.
/// </summary>
/// <typeparam name="array_type">The source typename array containing types to transform.</typeparam>
/// <typeparam name="functor_template">A template that transforms each type, receiving the type and its index. Must define ::new_type.</typeparam>
template<typename array_type, template<typename, typename_array_size_type> class functor_template>
struct apply {
private:
/// <summary>
/// Helper for applying the function to each element in the array.
/// </summary>
/// <typeparam name="helper_array_type">The array or remaining portion being processed.</typeparam>
/// <typeparam name="helper_functor_template">The transformation function template.</typeparam>
/// <typeparam name="index">Current position in the array being processed.</typeparam>
template<typename helper_array_type, template<typename, typename_array_size_type> class helper_functor_template, typename_array_size_type index>
struct apply_helper;
/// <summary>
/// Helper specialization for an empty array.
/// Notice that array_template uses typename... as a typename list. This is due to the fact that MSVC and GCC deduce template arguments differently.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="helper_functor_template">The transformation function template.</typeparam>
/// <typeparam name="index">Current position in the array being processed.</typeparam>
template<template<typename...> class array_template, template<typename, typename_array_size_type> class helper_functor_template, typename_array_size_type index>
struct apply_helper<array_template<>, helper_functor_template, index> {
/// <summary>
/// The resulting array when the input is empty.
/// </summary>
using new_array = typename_array<>;
};
/// <summary>
/// Specialization for processing the last element in the array.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">The type of the last element.</typeparam>
/// <typeparam name="helper_functor_template">The transformation function template.</typeparam>
/// <typeparam name="index">Current position in the array being processed.</typeparam>
template<template<typename...> class array_template, typename value_type, template<typename, typename_array_size_type> class helper_functor_template, typename_array_size_type index>
struct apply_helper<array_template<value_type>, helper_functor_template, index> {
/// <summary>
/// The resulting array with a single transformed type.
/// </summary>
using new_array = typename_array<typename helper_functor_template<value_type, index>::new_value>;
};
/// <summary>
/// Specialization for processing an array with multiple elements.
/// Recursively applies the function to each element and combines the results.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="other_type">The remaining types in the array.</typeparam>
/// <typeparam name="value_type">The current type being processed.</typeparam>
/// <typeparam name="helper_functor_template">The transformation function template.</typeparam>
/// <typeparam name="index">Current position in the array being processed.</typeparam>
template<template<typename...> class array_template, typename... other_type, typename value_type, template<typename, typename_array_size_type> class helper_functor_template, typename_array_size_type index>
struct apply_helper<array_template<value_type, other_type...>, helper_functor_template, index> {
/// <summary>
/// The array resulting from combining the transformed current element with
/// recursively processed remaining elements.
/// </summary>
using new_array = typename combine<
typename_array<typename helper_functor_template<value_type, index>::new_value>,
typename apply_helper<array_template<other_type...>, helper_functor_template, (index + 1)>::new_array
>::new_array;
};
public:
/// <summary>
/// The resulting array after applying the function to each element of the input array.
/// </summary>
using new_array = typename apply_helper<array_type, functor_template, 0>::new_array;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_APPLY_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_BASE_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_BASE_H
#include <type_traits>
/// <summary>
/// Type used for array indexing and size representation.
/// </summary>
using typename_array_size_type = long long;
/// <summary>
/// Special value indicating "no position" or "not found" in typename arrays.
/// </summary>
constexpr typename_array_size_type npos = -1;
/// <summary>
/// A compile-time container for a sequence of types.
/// </summary>
/// <typeparam name="arguments_type">The types to be stored in this array.</typeparam>
template<typename... arguments_type>
struct typename_array {
/// <summary>
/// The number of types contained in this array.
/// </summary>
static constexpr typename_array_size_type size = sizeof... (arguments_type);
/// <summary>
/// Transfers the types in this array to another template.
/// </summary>
/// <typeparam name="other_template">The destination template to receive the types.</typeparam>
template<template<typename... other_type> class other_template>
using acquire = other_template<arguments_type...>;
};
/// <summary>
/// Forward declaration for combining two typename arrays.
/// </summary>
/// <typeparam name="first_array_type">The first array of types.</typeparam>
/// <typeparam name="second_array_type">The second array of types.</typeparam>
template<typename first_array_type, typename second_array_type>
struct combine;
/// <summary>
/// Specialized implementation for combining two typename arrays.
/// Creates a new typename array that contains all types from both input arrays,
/// preserving their original order (first array's types followed by second array's types).
/// </summary>
/// <typeparam name="array_template">The template class of both arrays (typically typename_array).</typeparam>
/// <typeparam name="first_array_arguments_type">Types from the first array.</typeparam>
/// <typeparam name="second_array_arguments_type">Types from the second array.</typeparam>
template<template<typename...> class array_template, typename... first_array_arguments_type, typename... second_array_arguments_type>
struct combine<array_template<first_array_arguments_type...>, array_template<second_array_arguments_type...>> {
/// <summary>
/// The resulting array type after combination.
/// </summary>
using new_array = array_template<first_array_arguments_type..., second_array_arguments_type...>;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_BASE_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_CHECK_FOR_ALLOWED_TYPES_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_CHECK_FOR_ALLOWED_TYPES_H
#include "base.hpp"
#include "find.hpp"
/// <summary>
/// Verifies that all types in the array are present in the allowed_types list.
/// </summary>
/// <typeparam name="array_type">The array_type of types to validate.</typeparam>
/// <typeparam name="allowed_types">The array of permitted types.</typeparam>
template<typename array_type, typename allowed_types>
struct check_for_allowed_types {
private:
/// <summary>
/// Base helper structure for validation with termination condition.
/// Default specialization that indicates validation failure.
/// </summary>
/// <typeparam name="helper_array_type">Array being validated.</typeparam>
/// <typeparam name="helper_allowed_types">Array of allowed types.</typeparam>
/// <typeparam name="is_continue">Flag to continue validation or terminate with failure.</typeparam>
template<typename helper_array_type, typename helper_allowed_types, bool is_continue>
struct check_for_allowed_types_helper {
/// <summary>
/// Indicates validation failure.
/// </summary>
static constexpr bool is_valid = false;
};
/// <summary>
/// Specialization for empty array case - all validation is complete.
/// </summary>
/// <typeparam name="helper_array_type">Empty array (validation complete).</typeparam>
/// <typeparam name="helper_allowed_types">Array of allowed types.</typeparam>
template<typename helper_array_type, typename helper_allowed_types>
struct check_for_allowed_types_helper<helper_array_type, helper_allowed_types, true> {
/// <summary>
/// Indicates successful validation (all types are allowed).
/// </summary>
static constexpr bool is_valid = true;
};
/// <summary>
/// Specialization that recursively checks each type in the array.
/// Continues validation only if the current type is found in the allowed types.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">Current type being checked.</typeparam>
/// <typeparam name="other_type">Remaining types to check.</typeparam>
/// <typeparam name="helper_allowed_types">Array of allowed types.</typeparam>
template<template<typename...> class array_template, typename value_type, typename... other_type, typename helper_allowed_types>
struct check_for_allowed_types_helper<array_template<value_type, other_type...>, helper_allowed_types, true> {
/// <summary>
/// Recursively validates remaining types, continuing only if current type is allowed.
/// Uses find to determine if the current type exists in the allowed_types array.
/// </summary>
static constexpr bool is_valid = check_for_allowed_types_helper<
array_template<other_type...>,
helper_allowed_types,
(find<helper_allowed_types, value_type>::index != npos)
>::is_valid;
};
public:
/// <summary>
/// Result of validation. True if all types in the array are found
/// in the allowed_types list, false otherwise.
/// </summary>
static constexpr bool is_valid = check_for_allowed_types_helper<array_type, allowed_types, true>::is_valid;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_CHECK_FOR_ALLOWED_TYPES_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_COUNT_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_COUNT_H
#include "base.hpp"
/// <summary>
/// Counts occurrences of a specific type within a typename_array.
/// </summary>
/// <typeparam name="array_type">The typename array to search within.</typeparam>
/// <typeparam name="type_to_count">The type to count occurrences of.</typeparam>
template<typename array_type, typename type_to_count>
struct count {
private:
/// <summary>
/// Base helper structure for counting type occurrences.
/// Provides the final count when recursion is complete.
/// </summary>
/// <typeparam name="helper_array_type">Array or remaining portion being processed.</typeparam>
/// <typeparam name="helper_type_to_count">The type being counted.</typeparam>
/// <typeparam name="appearances_counter">Running count of occurrences found so far.</typeparam>
template<typename helper_array_type, typename helper_type_to_count, typename_array_size_type appearances_counter>
struct count_helper {
/// <summary>
/// The accumulated count of matching types.
/// </summary>
static constexpr typename_array_size_type counter = appearances_counter;
};
/// <summary>
/// Specialization for when the current type doesn't match the target type.
/// Continues recursion without incrementing the counter.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">Current type being examined (non-matching).</typeparam>
/// <typeparam name="other_types">Remaining types in the array.</typeparam>
/// <typeparam name="helper_type_to_count">The type being counted.</typeparam>
/// <typeparam name="appearances_counter">Running count of occurrences found so far.</typeparam>
template<template<typename...> class array_template, typename value_type, typename... other_types, typename helper_type_to_count, typename_array_size_type appearances_counter>
struct count_helper<array_template<value_type, other_types...>, helper_type_to_count, appearances_counter> {
/// <summary>
/// Continues counting in the rest of the array without incrementing.
/// </summary>
static constexpr typename_array_size_type counter = count_helper<
array_template<other_types...>,
helper_type_to_count,
appearances_counter
>::counter;
};
/// <summary>
/// Specialization for when the current type matches the target type.
/// Increments the counter and continues recursion.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="other_types">Remaining types in the array.</typeparam>
/// <typeparam name="helper_type_to_count">The type being counted (matched).</typeparam>
/// <typeparam name="appearances_counter">Running count of occurrences found so far.</typeparam>
template<template<typename...> class array_template, typename... other_types, typename helper_types_to_count, typename_array_size_type appearances_counter>
struct count_helper<array_template<helper_types_to_count, other_types...>, helper_types_to_count, appearances_counter> {
/// <summary>
/// Continues counting in the rest of the array after incrementing the counter.
/// </summary>
static constexpr typename_array_size_type counter = count_helper<
array_template<other_types...>,
helper_types_to_count,
(appearances_counter + 1)
>::counter;
};
public:
/// <summary>
/// The total number of occurrences of the specified type in the array.
/// </summary>
static constexpr typename_array_size_type counter = count_helper<array_type, type_to_count, 0>::counter;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_COUNT_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_CUT_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_CUT_H
#include "base.hpp"
/// <summary>
/// Extracts a subset of types from a typename array based on specified indices.
/// </summary>
/// <typeparam name="start_index">The starting index (inclusive) of the range to extract.</typeparam>
/// <typeparam name="end_index">The ending index (inclusive) of the range to extract.</typeparam>
/// <typeparam name="array_type">The source typename array to extract types from.</typeparam>
template<typename_array_size_type start_index, typename_array_size_type end_index, typename array_type>
struct cut {
private:
/// <summary>
/// Base helper template for cutting arrays.
/// </summary>
/// <typeparam name="use">Whether the current element should be included.</typeparam>
/// <typeparam name="index">Current position in the source array.</typeparam>
/// <typeparam name="helper_array_type">Type holding the remaining elements to process.</typeparam>
template<bool use, typename_array_size_type index, typename helper_array_type>
struct cut_helper {
/// <summary>
/// Empty result for base case or when no elements match the criteria.
/// </summary>
using new_array = typename_array<>;
};
/// <summary>
/// Specialization for processing elements that are outside the requested range.
/// Skips the current element and continues recursively.
/// </summary>
/// <typeparam name="use">Whether the current element should be included (false in this case).</typeparam>
/// <typeparam name="index">Current position in the source array.</typeparam>
/// <typeparam name="value_type">The current type being processed.</typeparam>
/// <typeparam name="other_types">The remaining types in the source array.</typeparam>
/// <typeparam name="array_template">The template class of the source array.</typeparam>
template<bool use, typename_array_size_type index, typename value_type, typename... other_types, template<typename...> class array_template>
struct cut_helper<use, index, array_template<value_type, other_types...>> {
static constexpr typename_array_size_type next_index = index + 1;
using new_array = typename cut_helper<
((next_index >= start_index) && (next_index <= end_index)),
next_index,
array_template<other_types...>
>::new_array;
};
/// <summary>
/// Specialization for processing elements that are within the requested range.
/// Includes the current element and continues recursively.
/// </summary>
/// <typeparam name="index">Current position in the source array.</typeparam>
/// <typeparam name="value_type">The current type being processed.</typeparam>
/// <typeparam name="other_types">The remaining types in the source array.</typeparam>
/// <typeparam name="array_template">The template class of the source array.</typeparam>
template<typename_array_size_type index, typename value_type, typename... other_types, template<typename...> class array_template>
struct cut_helper<true, index, array_template<value_type, other_types...>> {
static constexpr typename_array_size_type next_index = index + 1;
using new_array = typename combine<
array_template<value_type>,
typename cut_helper<
((next_index >= start_index) && (next_index <= end_index)),
next_index,
array_template<other_types...>
>::new_array
>::new_array;
};
public:
/// <summary>
/// The resulting array containing only the types from the specified index range.
/// Returns an empty array if start/end indices are invalid (if start > end,
/// start is negative, or end is beyond array bounds).
/// </summary>
using new_array = typename cut_helper<(start_index == 0) && (end_index >= start_index) && (end_index < array_type::size), 0, array_type>::new_array;
static_assert(start_index >= 0, "Invalid start index: must be non-negative.");
static_assert(end_index < array_type::size, "Invalid end index: must be within array bounds.");
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_CUT_H
#ifndef TYPENAME_ARRAY_TYPENAME_PRIMITIVES_ERASE_H
#define TYPENAME_ARRAY_TYPENAME_PRIMITIVES_ERASE_H
#include "base.hpp"
/// <summary>
/// Removes a type at the specified index from a typename array.
/// </summary>
/// <typeparam name="index_to_erase">The zero-based index of the type to remove.</typeparam>
/// <typeparam name="array_type">The typename array to remove the type from.</typeparam>
template<typename_array_size_type index_to_erase, typename array_type>
struct erase {
public:
/// <summary>
/// Helper template for implementation of type erasure at specific index.
/// </summary>
/// <typeparam name="index">Current index being processed during recursion.</typeparam>
/// <typeparam name="helper_array_type">The array being processed.</typeparam>
template<typename_array_size_type index, typename helper_array_type>
struct erase_helper;
/// <summary>
/// Specialization for when the current index matches the index to erase.
/// Skips the current type and keeps only the remaining types.
/// </summary>
/// <typeparam name="array_template">The template for the array container.</typeparam>
/// <typeparam name="value_type">The type at the index to be erased.</typeparam>
/// <typeparam name="other_types">The remaining types in the array.</typeparam>
template<template<typename...> class array_template, typename value_type, typename... other_types>
struct erase_helper<index_to_erase, array_template<value_type, other_types...>> {
/// <summary>
/// The resulting array after removing the type at the specified index.
/// </summary>
using new_array = typename_array<other_types...>;
};
/// <summary>
/// Specialization for when the current index doesn't match the index to erase.
/// Keeps the current type and continues processing the rest of the array.
/// </summary>
/// <typeparam name="index">Current index being processed during recursion.</typeparam>
/// <typeparam name="array_template">The template for the array container.</typeparam>
/// <typeparam name="value_type">The type at the current index.</typeparam>
/// <typeparam name="other_types">The remaining types in the array.</typeparam>
template<typename_array_size_type index, template<typename...> class array_template, typename value_type, typename... other_types>
struct erase_helper<index, array_template<value_type, other_types...>> {
/// <summary>
/// The resulting array, combining the current type with the result of processing the rest.
/// </summary>
using new_array = typename combine<
typename_array<value_type>,
typename erase_helper<index + 1, typename_array<other_types...>>::new_array
>::new_array;
};
public:
/// <summary>
/// The final array type after erasing the specified type.
/// </summary>
using new_array = typename erase_helper<0, array_type>::new_array;
static_assert(index_to_erase < array_type::size, "Index to erase is out of bounds for the array size.");
};
#endif // TYPENAME_ARRAY_TYPENAME_PRIMITIVES_ERASE_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_H
#include "base.hpp"
/// <summary>
/// Searches for a specific type in a typename array and provides its index.
/// </summary>
/// <typeparam name="array_type">The typename array to search within.</typeparam>
/// <typeparam name="helper_type_to_find">The type to find in the array.</typeparam>
template<typename array_type, typename type_to_find>
struct find {
private:
/// <summary>
/// Base helper structure for finding a type.
/// Default case when the type is not found - returns npos.
/// </summary>
/// <typeparam name="helper_array_type">The array or remaining portion being searched.</typeparam>
/// <typeparam name="helper_type_to_find">The type to find.</typeparam>
/// <typeparam name="index">Current position in the search.</typeparam>
template<typename helper_array_type, typename helper_type_to_find, typename_array_size_type index>
struct find_helper {
/// <summary>
/// When no match is found, returns npos (-1).
/// </summary>
static constexpr typename_array_size_type indx = npos;
};
/// <summary>
/// Specialization for when the current type doesn't match the target.
/// Continues the search in the rest of the array.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">Current type (non-matching).</typeparam>
/// <typeparam name="other_type">Remaining types in the array.</typeparam>
/// <typeparam name="helper_type_to_find">The type to find.</typeparam>
/// <typeparam name="index">Current position in the search.</typeparam>
template<template<typename...> class array_template, typename value_type, typename... other_type, typename helper_type_to_find, typename_array_size_type index>
struct find_helper<array_template<value_type, other_type...>, helper_type_to_find, index> {
/// <summary>
/// Recursively search in the remaining types, incrementing the index.
/// </summary>
static constexpr typename_array_size_type indx = find_helper<array_template<other_type...>, helper_type_to_find, index + 1>::indx;
};
/// <summary>
/// Specialization for when the current type matches the target.
/// Terminates the search and returns the current index.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="other_type">Remaining types in the array.</typeparam>
/// <typeparam name="helper_type_to_find">The matching type found.</typeparam>
/// <typeparam name="index">Current position in the search (result).</typeparam>
template<template<typename...> class array_template, typename... other_type, typename helper_type_to_find, typename_array_size_type index>
struct find_helper<array_template<helper_type_to_find, other_type...>, helper_type_to_find, index> {
/// <summary>
/// Returns the current index as the match is found.
/// </summary>
static constexpr typename_array_size_type indx = index;
};
public:
/// <summary>
/// The index of the first occurrence of type_to_find in the array,
/// or npos (-1) if the type is not present.
/// </summary>
static constexpr typename_array_size_type index = find_helper<array_type, type_to_find, 0>::indx;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_IF_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_IF_H
#include "base.hpp"
/// <summary>
/// Finds the first type in a typename array that satisfies a given predicate.
/// </summary>
/// <typeparam name="array_type">The typename array to search in.</typeparam>
/// <typeparam name="predicate_template">A template that takes a type and provides a static boolean 'value' member.</typeparam>
template<typename array_type, template<typename> class predicate_template>
struct find_if {
private:
/// <summary>
/// Base case for the find_if algorithm. Called when array is empty or recursion is complete.
/// </summary>
/// <typeparam name="index">Current position in the array.</typeparam>
/// <typeparam name="found">Indicates whether a matching type has been found.</typeparam>
/// <typeparam name="helper_array_type">The remaining part of the array to process.</typeparam>
template<typename_array_size_type index, bool found, typename helper_array_type>
struct find_if_helper {
static constexpr typename_array_size_type indx = npos;
};
/// <summary>
/// Recursive case for the find_if algorithm. Processes the next type in the array.
/// </summary>
/// <typeparam name="index">Current position in the array.</typeparam>
/// <typeparam name="found">Indicates whether a matching type has been found.</typeparam>
/// <typeparam name="value_type">The current type being checked.</typeparam>
/// <typeparam name="other_types">Remaining types in the array.</typeparam>
/// <typeparam name="array_template">The template used for the array.</typeparam>
template<typename_array_size_type index, typename value_type, typename... other_types, template<typename...> class array_template>
struct find_if_helper<index, false, array_template<value_type, other_types...>> {
static constexpr typename_array_size_type indx = find_if_helper<
index + 1,
predicate_template<value_type>::value,
array_template<other_types...>
>::indx;
};
/// <summary>
/// Specialization for when a matching type has been found. Stops recursion and returns the index.
/// </summary>
/// <typeparam name="index">Current position in the array.</typeparam>
/// <typeparam name="other_types">Remaining types in the array (ignored).</typeparam>
/// <typeparam name="array_template">The template used for the array.</typeparam>
template<typename_array_size_type index, typename... other_types, template<typename...> class array_template>
struct find_if_helper<index, true, array_template<other_types...>> {
static constexpr typename_array_size_type indx = index - 1;
};
public:
/// <summary>
/// The index of the first type in the array that satisfies the predicate, or npos if no such type exists.
/// </summary>
static constexpr typename_array_size_type index = find_if_helper<0, false, array_type>::indx;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_IF_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_N_APPEARANCE_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_N_APPEARANCE_H
#include "base.hpp"
/// <summary>
/// Finds the index of the Nth appearance of a specific type in a typename array.
/// </summary>
/// <typeparam name="array_type">The typename array to search in.</typeparam>
/// <typeparam name="type_to_find">The type to find within the array.</typeparam>
/// <typeparam name="counter">The occurrence number to find (1 for first appearance, 2 for second, etc.).</typeparam>
template<typename array_type, typename type_to_find, typename_array_size_type counter>
struct find_n_appearance {
private:
/// <summary>
/// Base helper struct for the recursive search algorithm.
/// Returns npos when the type is not found or count appearances don't exist.
/// </summary>
/// <typeparam name="helper_array_type">The array type being searched.</typeparam>
/// <typeparam name="helper_type_to_find">The type being searched for.</typeparam>
/// <typeparam name="helper_counter">The remaining occurrences to find.</typeparam>
/// <typeparam name="index">The current position in the array.</typeparam>
/// <typeparam name="dummy">Boolean flag to control template specialization selection.</typeparam>
template<typename helper_array_type, typename helper_type_to_find, typename_array_size_type helper_counter, typename_array_size_type index, bool dummy>
struct find_n_appearance_helper {
static constexpr typename_array_size_type indx = npos;
};
/// <summary>
/// Specialization for when the current type doesn't match the search type.
/// Continues searching through the rest of the array.
/// </summary>
/// <typeparam name="array_template">The template class of the array.</typeparam>
/// <typeparam name="value_type">The current type being examined (not matching the search type).</typeparam>
/// <typeparam name="helper_type_to_find">The type being searched for.</typeparam>
/// <typeparam name="other_types">The remaining types in the array.</typeparam>
/// <typeparam name="helper_counter">The remaining occurrences to find.</typeparam>
/// <typeparam name="index">The current position in the array.</typeparam>
template<template<typename...> class array_template, typename value_type, typename helper_type_to_find, typename... other_types, typename_array_size_type helper_counter, typename_array_size_type index>
struct find_n_appearance_helper<array_template<value_type, other_types...>, helper_type_to_find, helper_counter, index, true> {
static constexpr typename_array_size_type indx = find_n_appearance_helper<
array_template<other_types...>,
helper_type_to_find,
helper_counter,
(index + 1),
true
>::indx;
};
/// <summary>
/// Specialization for when the current type matches the search type.
/// Decrements the count and continues searching if more occurrences are needed.
/// </summary>
/// <typeparam name="array_template">The template class of the array.</typeparam>
/// <typeparam name="helper_type_to_find">The type being searched for and currently matched.</typeparam>
/// <typeparam name="other_types">The remaining types in the array.</typeparam>
/// <typeparam name="helper_counter">The remaining occurrences to find.</typeparam>
/// <typeparam name="index">The current position in the array.</typeparam>
template<template<typename...> class array_template, typename helper_type_to_find, typename... other_types, typename_array_size_type helper_counter, typename_array_size_type index>
struct find_n_appearance_helper<array_template<helper_type_to_find, other_types...>, helper_type_to_find, helper_counter, index, true> {
static constexpr typename_array_size_type indx = find_n_appearance_helper<
array_template<other_types...>,
helper_type_to_find,
(helper_counter - 1),
(index + 1),
((helper_counter - 1) != 0)
>::indx;
};
/// <summary>
/// Specialization for when the required number of occurrences has been found.
/// Returns the current index (minus 1) as the position of the last match.
/// </summary>
/// <typeparam name="array_template">The template class of the array.</typeparam>
/// <typeparam name="other_types">The remaining types in the array (no longer examined).</typeparam>
/// <typeparam name="helper_type_to_find">The type that was being searched for.</typeparam>
/// <typeparam name="index">The current position in the array.</typeparam>
template<template<typename...> class array_template, typename... other_types, typename helper_type_to_find, typename_array_size_type index>
struct find_n_appearance_helper<array_template<other_types...>, helper_type_to_find, 0, index, false> {
static constexpr typename_array_size_type indx = (index - 1);
};
public:
/// <summary>
/// The index of the Nth appearance of the specified type in the array,
/// or npos if the type doesn't appear N times.
/// </summary>
static constexpr typename_array_size_type index = find_n_appearance_helper<array_type, type_to_find, counter, 0, true>::indx;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_N_APPEARANCE_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_ONE_OF_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_ONE_OF_H
#include "base.hpp"
#include "find.hpp"
/// <summary>
/// Finds the first occurrence of any type from one array within another array.
/// </summary>
/// <typeparam name="array_type">The typename array to search within.</typeparam>
/// <typeparam name="array_to_find_type">The array of types to search for.</typeparam>
template<typename array_type, typename array_to_find_type>
struct find_one_of {
private:
/// <summary>
/// Base helper structure for finding any type from one array in another.
/// Returns npos when no match is found.
/// </summary>
/// <typeparam name="helper_array_type">Array or remaining portion being processed.</typeparam>
/// <typeparam name="helper_array_to_find_type">The array of types to search for.</typeparam>
/// <typeparam name="index">Current position in the search.</typeparam>
/// <typeparam name="is_found">Flag indicating if a match has been found.</typeparam>
template<typename helper_array_type, typename helper_array_to_find_type, typename_array_size_type index, bool is_found>
struct find_one_of_helper {
/// <summary>
/// Default case: no match found, return npos.
/// </summary>
static constexpr typename_array_size_type indx = npos;
};
/// <summary>
/// Specialization for when a match hasn't been found yet.
/// Continues recursion, checking if the current type exists in the array_to_find.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">Current type being examined.</typeparam>
/// <typeparam name="other_types">Remaining types in the array.</typeparam>
/// <typeparam name="helper_array_to_find_type">The array of types to search for.</typeparam>
/// <typeparam name="index">Current position in the search.</typeparam>
template<template<typename...> class array_template, typename value_type, typename... other_types, typename helper_array_to_find_type, typename_array_size_type index>
struct find_one_of_helper<array_template<value_type, other_types...>, helper_array_to_find_type, index, false> {
/// <summary>
/// Continues searching, using find to check if val exists in helper_array_to_find.
/// </summary>
static constexpr typename_array_size_type indx = find_one_of_helper<
array_template<other_types...>,
helper_array_to_find_type,
index + 1,
(find<helper_array_to_find_type, value_type>::index != -1)
>::indx;
};
/// <summary>
/// Specialization for when a match has been found.
/// Stops recursion and returns the current index.
/// </summary>
/// <typeparam name="helper_array_type">Array or remaining portion being processed.</typeparam>
/// <typeparam name="helper_array_to_find_type">The array of types to search for.</typeparam>
/// <typeparam name="index">Current position in the search.</typeparam>
template<typename helper_array_type, typename helper_array_to_find_type, typename_array_size_type index>
struct find_one_of_helper<helper_array_type, helper_array_to_find_type, index, true> {
/// <summary>
/// Match found, return the current index.
/// </summary>
static constexpr typename_array_size_type indx = index;
};
public:
/// <summary>
/// The index of the first occurrence of any type from array_to_find in array,
/// or npos if none are found.
/// </summary>
static constexpr typename_array_size_type index = find_one_of_helper<array_type, array_to_find_type, -1, false>::indx;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_ONE_OF_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_PRIORITY_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_PRIORITY_H
#include "base.hpp"
#include "find.hpp"
#include "value-wrapper.hpp"
/// <summary>
/// Finds the first type from array_to_find that exists in the array, returning its index.
/// </summary>
/// <typeparam name="array_type">The typename array to search within.</typeparam>
/// <typeparam name="array_to_find_type">Array of types to search for in priority order.</typeparam>
template<typename array_type, typename array_to_find_type>
struct find_priority {
private:
/// <summary>
/// Base helper structure for priority search implementation.
/// Returns npos when no matching types are found.
/// </summary>
/// <typeparam name="helper_array_type">Array being searched.</typeparam>
/// <typeparam name="helper_array_to_find_type">Remaining types to search for.</typeparam>
template<typename helper_array_type, typename helper_array_to_find_type>
struct find_priority_helper {
/// <summary>
/// Default result when no match is found.
/// </summary>
static constexpr typename_array_size_type get_value = npos;
};
/// <summary>
/// Specialization that recursively searches for types in priority order.
/// Attempts to find the first type (value_type), falling back to the next type if not found.
/// </summary>
/// <typeparam name="array_template">The template of the array_to_find.</typeparam>
/// <typeparam name="value_type">Current type to search for.</typeparam>
/// <typeparam name="other_types">Remaining types to search for if current type not found.</typeparam>
/// <typeparam name="helper_array_type">The array being searched.</typeparam>
template<template<typename...> class array_template, typename value_type, typename... other_types, typename helper_array_type>
struct find_priority_helper<helper_array_type, array_template<value_type, other_types...>> {
/// <summary>
/// Determines whether to continue with the current match or try the next type.
/// </summary>
using trailing_result = std::conditional_t<
(find<helper_array_type, value_type>::index == -1),
find_priority_helper<helper_array_type, array_template<other_types...>>,
value_wrapper<find<helper_array_type, value_type>::index>
>;
/// <summary>
/// The index of the first matching type found, or npos if none found.
/// Notice that "get_value" is used everywhere, this is due to the fact that it needs to be compatible with value_wrapper.
/// </summary>
static constexpr typename_array_size_type get_value = trailing_result::get_value;
};
public:
/// <summary>
/// The index of the first type from array_to_find found in array, or npos if none found.
/// Types are checked in the order they appear in array_to_find.
/// </summary>
static constexpr typename_array_size_type index = find_priority_helper<array_type, array_to_find_type>::get_value;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_FIND_PRIORITY_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_GET_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_GET_H
#include "base.hpp"
/// <summary>
/// Retrieves the type at a specific index within a typename_array.
/// </summary>
/// <typeparam name="index">The zero-based index of the element to retrieve.</typeparam>
/// <typeparam name="array_type">The typename array to retrieve from.</typeparam>
template<typename_array_size_type index, typename array_type>
struct get {
private:
/// <summary>
/// Helper structure for recursively accessing elements at a specific index.
/// </summary>
/// <typeparam name="counter">Current recursion depth/index position.</typeparam>
/// <typeparam name="helper_array_type">Array or remaining portion being processed.</typeparam>
template<typename_array_size_type counter, typename helper_array_type>
struct get_helper;
/// <summary>
/// Specialization for when the counter reaches zero (target index found).
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">The type at the target index position.</typeparam>
/// <typeparam name="other_types">Remaining types in the array (not used in this specialization).</typeparam>
template<template<typename...> class array_template, typename value_type, typename... other_types>
struct get_helper<0, array_template<value_type, other_types...>> {
/// <summary>
/// The type at the target index.
/// </summary>
using value = value_type;
};
/// <summary>
/// Specialization for recursive traversal when counter is greater than zero.
/// </summary>
/// <typeparam name="counter">Remaining steps to reach target index.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">Current type being examined (skipped).</typeparam>
/// <typeparam name="other_types">Remaining types in the array.</typeparam>
template<typename_array_size_type counter, template<typename...> class array_template, typename value_type, typename... other_types>
struct get_helper<counter, array_template<value_type, other_types...>> {
/// <summary>
/// Recursively access the next element by decrementing the counter.
/// </summary>
using value = typename get_helper<counter - 1, typename_array<other_types...>>::value;
};
public:
static_assert(index < array_type::size, "Index out of bounds in typename_array::get.");
static_assert(index >= 0, "Index must be greater than or equal to 0 in typename_array::get.");
/// <summary>
/// The type at the specified index position in the array.
/// </summary>
using value = typename get_helper<index, array_type>::value;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_GET_H
#ifndef TYPENAME_ARRAY_INCLUDE_ALL_NAMESPACE_H
#define TYPENAME_ARRAY_INCLUDE_ALL_NAMESPACE_H
namespace typename_array_primitives {
#include "apply.hpp"
#include "base.hpp"
#include "check-for-allowed-types.hpp"
#include "count.hpp"
#include "cut.hpp"
#include "erase.hpp"
#include "find.hpp"
#include "find-if.hpp"
#include "find-n-appearance.hpp"
#include "find-one-of.hpp"
#include "find-priority.hpp"
#include "get.hpp"
#include "insert.hpp"
#include "int-to-symbols.hpp"
#include "left-to-right.hpp"
#include "replace.hpp"
#include "replace-part.hpp"
#include "sort.hpp"
#include "static-calculator.hpp"
#include "static-pow.hpp"
#include "sum.hpp"
#include "symbols-to-int.hpp"
#include "typename-binder.hpp"
#include "unique-add.hpp"
#include "value-wrapper.hpp"
}
#endif // TYPENAME_ARRAY_INCLUDE_ALL_NAMESPACE_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_INSERT_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_INSERT_H
#include "base.hpp"
/// <summary>
/// Inserts a new type at a specified index within a typename_array.
/// </summary>
/// <typeparam name="insert_index">The index at which to insert the new type.</typeparam>
/// <typeparam name="array_type">The typename array to insert into.</typeparam>
/// <typeparam name="new_type">The type to insert.</typeparam>
template<typename_array_size_type insert_index, typename array_type, typename new_type>
struct insert {
private:
/// <summary>
/// Base helper structure for inserting a type at a specific index.
/// </summary>
/// <typeparam name="index">Current position in the array.</typeparam>
/// <typeparam name="helper_array_type">Array or remaining portion being processed.</typeparam>
/// <typeparam name="helper_new_type">The type being inserted.</typeparam>
template<typename_array_size_type index, typename helper_array_type, typename helper_new_type>
struct insert_helper {
using new_array = typename_array<>;
};
/// <summary>
/// Specialization for an empty array. If it was chosen, it means that
/// insertion is at index == array_type::size.
/// </summary>
/// <typeparam name="index">Current position in the array.</typeparam>
/// <typeparam name="array_template">Empty template array.</typeparam>
/// <typeparam name="helper_new_type">The type being inserted.</typeparam>
template<typename_array_size_type index, template<typename...> class array_template, typename helper_new_type>
struct insert_helper<index, array_template<>, helper_new_type> {
/// <summary>
/// If the array is empty, the new type is inserted immediately.
/// </summary>
using new_array = typename_array<helper_new_type>;
static_assert(index == array_type::size, "Should never fail.");
};
/// <summary>
/// Specialization for processing elements before the insertion point.
/// Preserves the current element and continues recursion.
/// </summary>
/// <typeparam name="index">Current position in the array.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="helper_new_type">The type being inserted.</typeparam>
/// <typeparam name="value_type">Current type being processed.</typeparam>
/// <typeparam name="other_types">Remaining types in the array.</typeparam>
template<typename_array_size_type index, template<typename...> class array_template, typename helper_new_type, typename value_type, typename... other_types>
struct insert_helper<index, array_template<value_type, other_types...>, helper_new_type> {
/// <summary>
/// Combines the current value with the result of processing the remaining array.
/// </summary>
using next = typename combine<
typename_array<value_type>,
typename insert_helper<index + 1, array_template<other_types...>, helper_new_type>::new_array
>::new_array;
/// <summary>
/// The resulting array after inserting the new element at current index.
/// </summary>
using current_inserted = typename combine<
typename_array<helper_new_type>,
array_template<value_type, other_types...>
>::new_array;
/// <summary>
/// A rather imperfect solution, initial implementation stopped
/// immediately after the insertion. However, it was not portable.
/// I was unable to think of anything better than this.
/// </summary>
using new_array = std::conditional_t<
index == insert_index,
current_inserted,
next
>;
};
public:
static_assert(insert_index <= array_type::size, "Insert index must be less than or equal to the size of the array typename_array::insert.");
static_assert(insert_index >= 0, "Insert index must be non-negative typename_array::insert.");
/// <summary>
/// The resulting array after inserting the new type at the specified index.
/// </summary>
using new_array = typename insert_helper<0, array_type, new_type>::new_array;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_INSERT_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_INT_TO_SYMBOLS_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_INT_TO_SYMBOLS_H
#include "base.hpp"
#include "value-wrapper.hpp"
/// <summary>
/// Converts an integer value to a typename_array of value_wrapper characters.
/// </summary>
/// <typeparam name="value">The integer value to convert to character symbols.</typeparam>
template<typename_array_size_type value>
struct int_to_symbols {
private:
/// <summary>
/// Helper structure for converting integers to character symbols.
/// Handles the recursive decomposition of multi-digit numbers.
/// </summary>
/// <typeparam name="helper_value">The current value being processed.</typeparam>
template<typename_array_size_type helper_value>
struct int_to_symbols_helper {
/// <summary>
/// Resulting array type containing character representations.
/// For single digits (0-9), creates a simple array with one character.
/// For multi-digit numbers, recursively processes the value.
/// </summary>
using array = std::conditional_t<
(helper_value < 10),
typename_array<value_wrapper<static_cast<char>('0' + helper_value)>>,
typename combine<
typename int_to_symbols<(helper_value / 10)>::array,
typename_array<value_wrapper<static_cast<char>('0' + (helper_value % 10))>>
>::new_array
>;
};
public:
/// <summary>
/// The resulting typename_array containing character representations of the integer.
/// Add minus sign if necessary.
/// </summary>
using array = std::conditional_t<
(value < 0),
typename combine<typename_array<value_wrapper<'-'>>, typename int_to_symbols_helper<-value>::array>::new_array,
typename int_to_symbols_helper<value>::array
>;
};
// Usually the style is that all specializations are defined inside base struct.
// However, here it is most likely impossible to implement without explicit full specialization for 0.
// This is because the recursive template specialization would not terminate for 0.
template<>
struct int_to_symbols<0> {
/// <summary>
/// Array containing the character '0'.
/// </summary>
using array = typename_array<value_wrapper<'0'>>;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_INT_TO_SYMBOLS_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_LEFT_TO_RIGHT_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_LEFT_TO_RIGHT_H
#include "base.hpp"
/// <summary>
/// Reverses the order of types in a typename_array, from left to right.
/// </summary>
/// <typeparam name="array_type">The typename array to reverse.</typeparam>
template<typename array_type>
struct left_to_right {
private:
/// <summary>
/// Base helper structure for reversing the order of types.
/// Provides the final reversed array when recursion is complete.
/// </summary>
/// <typeparam name="counter">Position counter for tracking progress through the array.</typeparam>
/// <typeparam name="helper_array_type">Array or remaining portion being processed.</typeparam>
template<typename_array_size_type counter, typename helper_array_type>
struct left_to_right_helper {
/// <summary>
/// The resulting array after reversal operations.
/// </summary>
using new_array = helper_array_type;
};
/// <summary>
/// Specialization that processes each type in the array from left to right,
/// building a new array with reversed order.
/// </summary>
/// <typeparam name="counter">Position counter for tracking progress through the array.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">Current type being processed.</typeparam>
/// <typeparam name="other_types">Remaining types in the array.</typeparam>
template<typename_array_size_type counter, template<typename...> class array_template, typename value_type, typename... other_types>
struct left_to_right_helper<counter, array_template<value_type, other_types...>> {
/// <summary>
/// Recursively builds the reversed array by combining the result of
/// processing remaining types with the current type.
/// </summary>
using new_array = typename combine<
typename left_to_right_helper<counter - 1, typename_array<other_types...>>::new_array,
typename_array<value_type>
>::new_array;
};
public:
/// <summary>
/// The resulting array with types in reversed order.
/// </summary>
using new_array = typename left_to_right_helper<array_type::size, array_type>::new_array;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_LEFT_TO_RIGHT_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_REPLACE_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_REPLACE_H
#include "base.hpp"
/// <summary>
/// Replaces a type at a specific index in a typename array with a new type.
/// </summary>
/// <typeparam name="replace_index">The index where the type will be replaced.</typeparam>
/// <typeparam name="array_type">The source typename array.</typeparam>
/// <typeparam name="new_type">The new type that will replace the existing one.</typeparam>
template<typename_array_size_type replace_index, typename array_type, typename new_type>
struct replace {
private:
/// <summary>
/// Forward declaration of the helper structure for replacing types in the array.
/// </summary>
/// <typeparam name="index">Current position in the array being processed.</typeparam>
/// <typeparam name="helper_array_type">The array or remaining portion being processed.</typeparam>
/// <typeparam name="helper_new_type">The new type to insert at the target position.</typeparam>
template<typename_array_size_type index, typename helper_array_type, typename helper_new_type>
struct replace_helper;
/// <summary>
/// Specialization for when the current position matches the target replacement index.
/// Replaces the first type with the new type and maintains the rest of the types.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">The original type being replaced.</typeparam>
/// <typeparam name="other_types">The remaining types in the array.</typeparam>
/// <typeparam name="helper_new_type">The new type to replace with.</typeparam>
template<template<typename...> class array_template, typename value_type, typename... other_types, typename helper_new_type>
struct replace_helper<replace_index, array_template<value_type, other_types...>, helper_new_type> {
/// <summary>
/// The resulting array after replacement, with the new type at the target position.
/// </summary>
using new_array = array_template<helper_new_type, other_types...>;
};
/// <summary>
/// Specialization for when the current position doesn't match the target replacement index.
/// Keeps the current type and continues recursion for the rest of the array.
/// </summary>
/// <typeparam name="index">Current position in the array being processed.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">The current type to keep.</typeparam>
/// <typeparam name="other_types">The remaining types in the array.</typeparam>
/// <typeparam name="helper_new_type">The new type to insert at the target position.</typeparam>
template<typename_array_size_type index, template<typename...> class array_template, typename value_type, typename... other_types, typename helper_new_type>
struct replace_helper<index, array_template<value_type, other_types...>, helper_new_type> {
/// <summary>
/// The resulting array from keeping the current type and processing the rest of the array.
/// Uses combine to prepend the current type to the array resulting from the recursive call.
/// </summary>
using new_array = typename combine<typename_array<value_type>, typename replace_helper<index + 1, array_template<other_types...>, helper_new_type>::new_array>::new_array;
};
public:
static_assert(replace_index < array_type::size, "Replace index must be less than the size of the array.");
static_assert(replace_index >= 0, "Replace index must be non-negative.");
/// <summary>
/// The resulting array after replacing the type at the specified index.
/// </summary>
using new_array = typename replace_helper<0, array_type, new_type>::new_array;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_REPLACE_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_REPLACE_PART_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_REPLACE_PART_H
#include "base.hpp"
#include "cut.hpp"
/// <summary>
/// Replaces a section of a typename_array with another type or array.
/// </summary>
/// <typeparam name="array_type">The original typename array to modify.</typeparam>
/// <typeparam name="start">The starting index of the section to replace (inclusive).</typeparam>
/// <typeparam name="end">The ending index of the section to replace (inclusive).</typeparam>
/// <typeparam name="to_place_type">The type (must be wrapped into typename_array) or array to insert in place of the removed section.</typeparam>
template<typename array_type, typename_array_size_type start, typename_array_size_type end, typename to_place_type>
struct replace_part {
/// <summary>
/// The resulting array type after replacement.
/// Combines three parts: the section before the replaced range,
/// the inserted type, and the section after the replaced range.
/// </summary>
using new_array = typename combine<
typename combine<typename cut<0, (start - 1), array_type>::new_array, to_place_type>::new_array,
typename cut<end + 1, array_type::size - 1, array_type>::new_array>::new_array;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_REPLACE_PART_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_SORT_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_SORT_H
#include "base.hpp"
#include "get.hpp"
#include "cut.hpp"
/// <summary>
/// Sorts a typename array according to a specified predicate.
/// </summary>
/// <typeparam name="array_type">The typename array to be sorted.</typeparam>
/// <typeparam name="predicate_template">Binary predicate template that determines sort order. Returns true if first type ordered before second.</typeparam>
template<typename array_type, template<typename, typename> class predicate_template>
struct sort {
private:
/// <summary>
/// Helper structure to merge two sorted arrays into a single sorted array.
/// </summary>
/// <typeparam name="first_array_type">The first sorted array.</typeparam>
/// <typeparam name="second_array_type">The second sorted array.</typeparam>
template<typename first_array_type, typename second_array_type>
struct combine_sorted_arrays;
/// <summary>
/// Specialization for when the second array is empty or invalid.
/// </summary>
/// <typeparam name="other_type">The type of the second (empty) array.</typeparam>
/// <typeparam name="first_value_type">The first type in the first array.</typeparam>
/// <typeparam name="first_other_types">Remaining types in the first array.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
template<typename other_type, typename first_value_type, typename... first_other_types, template<typename...> class array_template>
struct combine_sorted_arrays<array_template<first_value_type, first_other_types...>, other_type> {
/// <summary>
/// Returns the first array unchanged when the second array is empty.
/// </summary>
using new_array = array_template<first_value_type, first_other_types...>;
};
/// <summary>
/// Specialization for when the first array is empty or invalid.
/// </summary>
/// <typeparam name="other_type">The type of the first (empty) array.</typeparam>
/// <typeparam name="second_value_type">The first type in the second array.</typeparam>
/// <typeparam name="second_other_types">Remaining types in the second array.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
template<typename other_type, typename second_value_type, typename... second_other_types, template<typename...> class array_template>
struct combine_sorted_arrays<other_type, array_template<second_value_type, second_other_types...>> {
/// <summary>
/// Returns the second array unchanged when the first array is empty.
/// </summary>
using new_array = array_template<second_value_type, second_other_types...>;
};
/// <summary>
/// Specialization for combining two non-empty arrays by comparing their first elements.
/// </summary>
/// <typeparam name="first_value_type">The first type in the first array.</typeparam>
/// <typeparam name="first_other_types">Remaining types in the first array.</typeparam>
/// <typeparam name="second_value_type">The first type in the second array.</typeparam>
/// <typeparam name="second_other_types">Remaining types in the second array.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
template<typename first_value_type, typename... first_other_types, typename second_value_type, typename... second_other_types, template<typename...> class array_template>
struct combine_sorted_arrays<array_template<first_value_type, first_other_types...>, array_template<second_value_type, second_other_types...>> {
/// <summary>
/// Determines if the first value should come before the second value according to the predicate.
/// </summary>
static constexpr bool is_value_before = predicate_template<first_value_type, second_value_type>::value;
/// <summary>
/// The type to be placed at the front of the merged array.
/// </summary>
using first_val = std::conditional_t<is_value_before, first_value_type, second_value_type>;
/// <summary>
/// The remaining arrays to be merged after removing the selected first element.
/// </summary>
using arrays = std::conditional_t<
is_value_before,
array_template<array_template<first_other_types...>, array_template<second_value_type, second_other_types...>>,
array_template<array_template<first_value_type, first_other_types...>, array_template<second_other_types...>>
>;
/// <summary>
/// The merged array combining the selected first element with the recursively merged remainder.
/// </summary>
using new_array = typename combine<array_template<first_val>,
typename combine_sorted_arrays<typename get<0, arrays>::value,
typename get<1, arrays>::value>::new_array
>::new_array;
};
/// <summary>
/// Base helper structure for sorting arrays using merge sort algorithm.
/// </summary>
/// <typeparam name="first_type">First portion of the array to sort.</typeparam>
/// <typeparam name="second_type">Second portion of the array to sort.</typeparam>
template<typename first_type, typename second_type>
struct sort_help {
/// <summary>
/// Default case returns an empty array.
/// </summary>
using new_array = typename_array<>;
};
/// <summary>
/// Specialization for when the first portion is empty.
/// </summary>
/// <typeparam name="first_type">Empty or invalid first portion.</typeparam>
/// <typeparam name="value_type">First type in the second portion.</typeparam>
/// <typeparam name="other_types">Remaining types in the second portion.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
template<typename first_type, typename value_type, typename... other_types, template<typename...> class array_template>
struct sort_help<first_type, array_template<value_type, other_types...>> {
/// <summary>
/// Returns the second portion unchanged when the first portion is empty.
/// </summary>
using new_array = array_template<value_type, other_types...>;
};
/// <summary>
/// Specialization for when the second portion is empty.
/// </summary>
/// <typeparam name="second_type">Empty or invalid second portion.</typeparam>
/// <typeparam name="value_type">First type in the first portion.</typeparam>
/// <typeparam name="other_types">Remaining types in the first portion.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
template<typename second_type, typename value_type, typename... other_types, template<typename...> class array_template>
struct sort_help<array_template<value_type, other_types...>, second_type> {
/// <summary>
/// Returns the first portion unchanged when the second portion is empty.
/// </summary>
using new_array = array_template<value_type, other_types...>;
};
/// <summary>
/// Specialization for sorting two single-element arrays.
/// </summary>
/// <typeparam name="first_other_type">The type in the first array.</typeparam>
/// <typeparam name="second_other_type">The type in the second array.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
template<typename first_other_type, typename second_other_type, template<typename> class array_template>
struct sort_help<array_template<first_other_type>, array_template<second_other_type>> {
/// <summary>
/// The first single-element array.
/// </summary>
using first_array_type = array_template<first_other_type>;
/// <summary>
/// The second single-element array.
/// </summary>
using second_array_type = array_template<second_other_type>;
/// <summary>
/// Merges the two single-element arrays in sorted order.
/// </summary>
using new_array = typename combine_sorted_arrays<first_array_type, second_array_type>::new_array;
};
/// <summary>
/// Specialization for sorting two multi-element arrays using divide-and-conquer approach.
/// </summary>
/// <typeparam name="first_value_type">First type in the first array.</typeparam>
/// <typeparam name="second_value_type">First type in the second array.</typeparam>
/// <typeparam name="first_other_types">Remaining types in the first array.</typeparam>
/// <typeparam name="second_other_types">Remaining types in the second array.</typeparam>
/// <typeparam name="array_template">The template of the array.</typeparam>
template<typename first_value_type, typename second_value_type, typename... first_other_types, typename... second_other_types, template<typename...> class array_template>
struct sort_help<array_template<first_value_type, first_other_types...>, array_template<second_value_type, second_other_types...>> {
/// <summary>
/// The first array to be sorted.
/// </summary>
using first_array_type = array_template<first_value_type, first_other_types...>;
/// <summary>
/// The second array to be sorted.
/// </summary>
using second_array_type = array_template<second_value_type, second_other_types...>;
/// <summary>
/// Midpoint index of the first array.
/// </summary>
static constexpr typename_array_size_type first = first_array_type::size / 2;
/// <summary>
/// Midpoint index of the second array.
/// </summary>
static constexpr typename_array_size_type second = second_array_type::size / 2;
/// <summary>
/// Recursively sorts the first array by dividing it and merging the sorted halves.
/// </summary>
using first_half = typename sort_help<
typename cut<0, first - 1, first_array_type>::new_array,
typename cut<first, first_array_type::size - 1, first_array_type>::new_array
>::new_array;
/// <summary>
/// Recursively sorts the second array by dividing it and merging the sorted halves.
/// </summary>
using second_half = typename sort_help<
typename cut<0, second - 1, second_array_type>::new_array,
typename cut<second, second_array_type::size - 1, second_array_type>::new_array
>::new_array;
/// <summary>
/// Merges the two sorted arrays to produce the final sorted result.
/// </summary>
using new_array = typename combine_sorted_arrays<first_half, second_half>::new_array;
};
/// <summary>
/// Midpoint index of the input array.
/// </summary>
static constexpr typename_array_size_type half = array_type::size / 2;
public:
/// <summary>
/// The sorted array produced by applying merge sort to the input array.
/// </summary>
using new_array = typename sort_help<
typename cut<0, half - 1, array_type>::new_array,
typename cut<half, array_type::size - 1, array_type>::new_array
>::new_array;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_SORT_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_STATIC_CALC_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_STATIC_CALC_H
#include "base.hpp"
#include "value-wrapper.hpp"
#include "cut.hpp"
#include "find-one-of.hpp"
#include "left-to-right.hpp"
#include "find-priority.hpp"
#include "symbols-to-int.hpp"
#include "get.hpp"
#include "int-to-symbols.hpp"
#include "replace-part.hpp"
#include "typename-binder.hpp"
/// <summary>
/// Compiles and evaluates a mathematical expression at compile time using type-level computation.
/// Supports basic arithmetic operations (+, -, *, /, %) and parentheses.
/// Negative or fractional values are NOT supported and will break this.
/// </summary>
/// <typeparam name="symbols_types">A sequence of value types representing the characters in the expression.</typeparam>
template<typename... symbols_types>
struct static_calculator {
private:
/// <summary>
/// Array of recognized operators and parentheses that can appear in expressions.
/// </summary>
using expressions_symbols_type = typename_array<value_wrapper<'('>, value_wrapper<'%'>, value_wrapper<'/'>, value_wrapper<'*'>, value_wrapper<'+'>, value_wrapper<'-'>, value_wrapper<')'>>;
/// <summary>
/// Enumeration of expression types to differentiate between regular expressions and parenthesized expressions.
/// </summary>
enum class expression_type {
regular_expression,
parentheses
};
/// <summary>
/// Finds the matching closing parenthesis for an opening parenthesis.
/// </summary>
/// <typeparam name="array_type">The array containing the expression.</typeparam>
/// <typeparam name="start_index">The index of the opening parenthesis.</typeparam>
template<typename array_type, typename_array_size_type start_index>
struct find_last_closed_parentheses {
private:
/// <summary>
/// Helper structure that tracks parenthesis nesting to find the matching closing parenthesis.
/// </summary>
/// <typeparam name="helper_array_type">The remaining portion of the array being processed.</typeparam>
/// <typeparam name="parentheses_count">Current nesting level of parentheses.</typeparam>
/// <typeparam name="index">Current position being examined.</typeparam>
template<typename helper_array_type, typename_array_size_type parentheses_count, typename_array_size_type index>
struct find_last_closed_parentheses_helper {
/// <summary>
/// The index where the search terminates.
/// </summary>
static constexpr typename_array_size_type indx = index;
};
/// <summary>
/// Recursive helper that processes each character and tracks parenthesis nesting.
/// </summary>
template<template<typename...> class array_template, typename... other_types, typename_array_size_type parentheses_count, typename_array_size_type index, char character>
struct find_last_closed_parentheses_helper<array_template<value_wrapper<character>, other_types...>, parentheses_count, index> {
/// <summary>
/// Updates the parentheses count based on encountered parentheses.
/// Increments for '(', decrements for ')', otherwise no change.
/// </summary>
static constexpr typename_array_size_type parentheses_count_new =
(character == '(')
? (parentheses_count + 1)
: (character == ')') ? (parentheses_count - 1) : parentheses_count;
/// <summary>
/// The index of the matching closing parenthesis, or continues the search.
/// Returns the current index if parentheses_count becomes zero (matching parenthesis found).
/// </summary>
static constexpr typename_array_size_type indx = (parentheses_count == 0) ? index : find_last_closed_parentheses_helper<array_template<other_types...>, parentheses_count_new, (index + 1)>::indx;
};
public:
/// <summary>
/// The index of the closing parenthesis that matches the opening parenthesis at start_index.
/// </summary>
static constexpr typename_array_size_type index = find_last_closed_parentheses_helper<array_type, 1, start_index>::indx;
};
/// <summary>
/// Determines the boundaries of an expression around an operator.
/// For regular expressions, finds the complete left and right operands.
/// </summary>
/// <typeparam name="character">The operator character.</typeparam>
/// <typeparam name="array_type">The array containing the expression.</typeparam>
/// <typeparam name="index">The index of the operator.</typeparam>
template<char character, typename array_type, typename_array_size_type index>
struct find_boundaries {
/// <summary>
/// The right half of the expression after the operator.
/// </summary>
using expression_right_half_type = typename cut<(index + 1), (array_type::size - 1), array_type>::new_array;
/// <summary>
/// The index of the next operator in the right half, or -1 if none exists.
/// </summary>
static constexpr typename_array_size_type right_half_end = find_one_of<expression_right_half_type, expressions_symbols_type>::index;
/// <summary>
/// Type representing the true end index of the right operand.
/// If no more operators are found, uses the end of the array.
/// </summary>
using true_right_half_end_type =
std::conditional_t<(right_half_end == -1),
value_wrapper<(array_type::size - 1)>,
value_wrapper<(index + right_half_end)>>;
/// <summary>
/// The end index of the right operand.
/// </summary>
static constexpr typename_array_size_type true_right_half_end = true_right_half_end_type::get_value;
/// <summary>
/// The left half of the expression before the operator, reversed for search.
/// </summary>
using expression_left_half_type = typename left_to_right<typename cut<0, (index - 1), array_type>::new_array>::new_array;
/// <summary>
/// The index of the previous operator in the left half, or -1 if none exists.
/// </summary>
static constexpr typename_array_size_type left_half_end = find_one_of<expression_left_half_type, expressions_symbols_type>::index;
/// <summary>
/// Type representing the true start index of the left operand.
/// If no previous operators are found, uses the start of the array.
/// </summary>
using expression_true_left_half_end_type =
std::conditional_t<(left_half_end == -1),
value_wrapper<static_cast<typename_array_size_type>(0)>,
value_wrapper<index - left_half_end>>;
/// <summary>
/// The start index of the left operand.
/// </summary>
static constexpr typename_array_size_type true_left_half_end = expression_true_left_half_end_type::get_value;
/// <summary>
/// Array containing information about the expression boundaries:
/// [expression type, left boundary, right boundary, operator index]
/// </summary>
using expression_boundaries_type = typename_array<
value_wrapper<expression_type::regular_expression>,
value_wrapper<true_left_half_end>,
value_wrapper<true_right_half_end>,
value_wrapper<index>
>;
};
/// <summary>
/// Specialization for parenthesized expressions, which have different boundary rules.
/// </summary>
/// <typeparam name="array_type">The array containing the expression.</typeparam>
/// <typeparam name="index">The index of the opening parenthesis.</typeparam>
template<typename array_type, typename_array_size_type index>
struct find_boundaries<'(', array_type, index> {
/// <summary>
/// The right half of the expression after the opening parenthesis.
/// </summary>
using right_half_of_expression = typename cut<(index + 1), (array_type::size - 1), array_type>::new_array;
/// <summary>
/// The index of the matching closing parenthesis.
/// </summary>
static constexpr typename_array_size_type last_closed_parentheses = find_last_closed_parentheses<right_half_of_expression, index>::index;
/// <summary>
/// Array containing information about the parenthesized expression boundaries:
/// [expression type, opening parenthesis index, closing parenthesis index, opening parenthesis index]
/// </summary>
using expression_boundaries_type = typename_array<
value_wrapper<expression_type::parentheses>,
value_wrapper<index>,
value_wrapper<last_closed_parentheses>,
value_wrapper<index>>;
};
/// <summary>
/// Finds the expression with the highest operator precedence to evaluate next.
/// </summary>
/// <typeparam name="helper_symbols_types">The symbols in the expression.</typeparam>
template<typename... helper_symbols_types>
struct find_expression_with_highest_priority {
/// <summary>
/// The index of the highest priority operator in the expression.
/// </summary>
static constexpr typename_array_size_type highest_priority_symbol = find_priority<typename_array<helper_symbols_types...>, expressions_symbols_type>::index;
/// <summary>
/// The type of the highest priority operator.
/// </summary>
using symbol = typename get<highest_priority_symbol, typename_array<helper_symbols_types...>>::value;
/// <summary>
/// Array containing the expression boundaries and the operator symbol.
/// </summary>
using array = typename combine<
typename find_boundaries<symbol::get_value, typename_array<helper_symbols_types...>, highest_priority_symbol>::expression_boundaries_type,
typename_array<symbol>
>::new_array;
};
/// <summary>
/// Calculates the result of a simple (atomic) expression based on its type and operands.
/// </summary>
/// <typeparam name="ex_type">The type of the expression (regular or parenthesized).</typeparam>
/// <typeparam name="simple_expression_info_type">Information about the expression boundaries.</typeparam>
/// <typeparam name="array_type">The array containing the expression.</typeparam>
template<expression_type ex_type, typename simple_expression_info_type, typename array_type>
struct calculate_simple_expression {
private:
/// <summary>
/// Helper structure for performing different calculations based on operator.
/// </summary>
/// <typeparam name="symbol">The operator character.</typeparam>
/// <typeparam name="left_part_type">The left operand.</typeparam>
/// <typeparam name="right_part_type">The right operand.</typeparam>
template<char symbol, typename left_part_type, typename right_part_type>
struct perform;
/// <summary>
/// Specialization for the modulo operator (%).
/// </summary>
template<typename left_part_type, typename right_part_type>
struct perform<'%', left_part_type, right_part_type> {
/// <summary>
/// The result of the modulo operation.
/// </summary>
static constexpr typename_array_size_type value = left_part_type::template acquire<symbols_to_int>::result % right_part_type::template acquire<symbols_to_int>::result;
};
/// <summary>
/// Specialization for the multiplication operator (*).
/// </summary>
template<typename left_part_type, typename right_part_type>
struct perform<'*', left_part_type, right_part_type> {
/// <summary>
/// The result of the multiplication operation.
/// </summary>
static constexpr typename_array_size_type value = left_part_type::template acquire<symbols_to_int>::result * right_part_type::template acquire<symbols_to_int>::result;
};
/// <summary>
/// Specialization for the division operator (/).
/// </summary>
template<typename left_part_type, typename right_part_type>
struct perform<'/', left_part_type, right_part_type> {
/// <summary>
/// The result of the division operation.
/// </summary>
static constexpr typename_array_size_type value = left_part_type::template acquire<symbols_to_int>::result / right_part_type::template acquire<symbols_to_int>::result;
};
/// <summary>
/// Specialization for the addition operator (+).
/// </summary>
template<typename left_part_type, typename right_part_type>
struct perform<'+', left_part_type, right_part_type> {
/// <summary>
/// The result of the addition operation.
/// </summary>
static constexpr typename_array_size_type value = left_part_type::template acquire<symbols_to_int>::result + right_part_type::template acquire<symbols_to_int>::result;
};
/// <summary>
/// Specialization for the subtraction operator (-).
/// </summary>
template<typename left_part_type, typename right_part_type>
struct perform<'-', left_part_type, right_part_type> {
/// <summary>
/// The result of the subtraction operation.
/// </summary>
static constexpr typename_array_size_type value = left_part_type::template acquire<symbols_to_int>::result - right_part_type::template acquire<symbols_to_int>::result;
};
public:
/// <summary>
/// The start index of the expression.
/// </summary>
using start_type = typename get<1, simple_expression_info_type>::value;
/// <summary>
/// The end index of the expression.
/// </summary>
using end_type = typename get<2, simple_expression_info_type>::value;
/// <summary>
/// The index of the operator.
/// </summary>
using expression_index_type = typename get<3, simple_expression_info_type>::value;
/// <summary>
/// The operator symbol.
/// </summary>
using expression_character_type = typename get<4, simple_expression_info_type>::value;
/// <summary>
/// The result of the calculation converted back to a sequence of digit symbols.
/// </summary>
using calculated_symbols_type = typename int_to_symbols<perform<expression_character_type::get_value,
typename cut<start_type::get_value, (expression_index_type::get_value - 1), array_type>::new_array,
typename cut<(expression_index_type::get_value + 1), end_type::get_value, array_type>::new_array>::value
>::array;
};
/// <summary>
/// Main recursion helper for evaluating expressions.
/// Continues recursion as long as operators remain in the expression.
/// </summary>
/// <typeparam name="is_changeable_type">Flag indicating if the expression still contains operators.</typeparam>
/// <typeparam name="helper_symbols_types">The symbols in the expression.</typeparam>
template<typename is_changeable_type, typename... helper_symbols_types>
struct static_calculator_helper {
/// <summary>
/// The current expression as an array.
/// </summary>
using array_type = typename_array<helper_symbols_types...>;
/// <summary>
/// Information about the highest priority expression to evaluate next.
/// </summary>
using simple_expression_info_type = typename find_expression_with_highest_priority<helper_symbols_types...>::array;
/// <summary>
/// The type of the expression (regular or parenthesized).
/// </summary>
using expression_type = typename get<0, simple_expression_info_type>::value;
/// <summary>
/// The start index of the expression.
/// </summary>
using start_type = typename get<1, simple_expression_info_type>::value;
/// <summary>
/// The end index of the expression.
/// </summary>
using end_type = typename get<2, simple_expression_info_type>::value;
/// <summary>
/// The result symbols of calculating the current expression.
/// </summary>
using new_symbols_type = typename calculate_simple_expression<expression_type::get_value, simple_expression_info_type, array_type>::calculated_symbols_type;
/// <summary>
/// The array with the calculated expression replaced.
/// </summary>
using new_array_type = typename replace_part<array_type, start_type::get_value, end_type::get_value, new_symbols_type>::new_array;
/// <summary>
/// Binder for continuing recursion if operators remain.
/// </summary>
using binder_type = typename_binder<static_calculator_helper, value_wrapper<(find_one_of<new_array_type, expressions_symbols_type>::index != -1)>>;
/// <summary>
/// The value of the expression after recursive evaluation.
/// </summary>
static constexpr typename_array_size_type value = new_array_type::template acquire<binder_type::template bind>::value;
};
/// <summary>
/// Terminal case for recursion when no operators remain.
/// Converts the remaining digit symbols to an integer.
/// </summary>
template<typename... helper_symbols_types>
struct static_calculator_helper<value_wrapper<false>, helper_symbols_types...> {
/// <summary>
/// The final value of the expression.
/// </summary>
static constexpr typename_array_size_type value = symbols_to_int<helper_symbols_types...>::result;
};
/// <summary>
/// Specialization for calculating parenthesized expressions.
/// Handles the recursion into evaluating the expression inside parentheses.
/// </summary>
template<typename simple_expression_info_type, typename array_type>
struct calculate_simple_expression<expression_type::parentheses, simple_expression_info_type, array_type> {
/// <summary>
/// The index of the opening parenthesis.
/// </summary>
using start_type = typename get<1, simple_expression_info_type>::value;
/// <summary>
/// The index of the closing parenthesis.
/// </summary>
using end_type = typename get<2, simple_expression_info_type>::value;
/// <summary>
/// The expression inside the parentheses.
/// </summary>
using in_parentheses_type = typename cut<(start_type::get_value + 1), (end_type::get_value - 1), array_type>::new_array;
/// <summary>
/// Binder for recursively evaluating the parenthesized expression.
/// </summary>
using binder_type = typename_binder<static_calculator_helper, value_wrapper<(find_one_of<in_parentheses_type, expressions_symbols_type>::index != -1)>>;
/// <summary>
/// The result of evaluating the parenthesized expression, converted to digit symbols.
/// </summary>
using calculated_symbols_type = typename int_to_symbols<in_parentheses_type::template acquire<binder_type::template bind>::value>::array;
};
public:
/// <summary>
/// The final result of evaluating the mathematical expression.
/// </summary>
static constexpr typename_array_size_type result = static_calculator_helper<value_wrapper<(find_one_of<typename_array<symbols_types...>, expressions_symbols_type>::index != -1)>, symbols_types...>::value;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_STATIC_CALC_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_STATIC_POW_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_STATIC_POW_H
#include "base.hpp"
/// <summary>
/// Calculates the power of a value at compile time.
/// </summary>
/// <typeparam name="value">The base value to be raised to a power.</typeparam>
/// <typeparam name="counter">The exponent to raise the base value to.</typeparam>
template<typename_array_size_type value, typename_array_size_type counter>
struct static_pow {
private:
/// <summary>
/// Helper structure for calculating power using recursive template instantiation.
/// </summary>
/// <typeparam name="helper_value">The base value being raised to a power.</typeparam>
/// <typeparam name="helper_counter">The remaining exponent to process.</typeparam>
template<typename_array_size_type helper_value, typename_array_size_type helper_counter>
struct static_pow_helper {
/// <summary>
/// Recursively calculates the power by multiplying the base value by the result of the next lower power.
/// </summary>
static constexpr typename_array_size_type result = helper_value * static_pow<helper_value, (helper_counter - 1)>::result;
};
/// <summary>
/// Specialization for the base case when exponent is zero.
/// Any number raised to the power of zero equals one.
/// </summary>
/// <typeparam name="helper_value">The base value (not used in calculation when exponent is zero).</typeparam>
template<typename_array_size_type helper_value>
struct static_pow_helper<helper_value, 0> {
/// <summary>
/// The result of any number raised to the power of zero is one.
/// </summary>
static constexpr typename_array_size_type result = 1;
};
public:
static_assert(counter >= 0, "Exponent must be non-negative.");
/// <summary>
/// The final result of raising the base value to the specified power.
/// </summary>
static constexpr typename_array_size_type result = static_pow_helper<value, counter>::result;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_STATIC_POW_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_SUM_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_SUM_H
#include "base.hpp"
/// <summary>
/// Calculates the sum of values associated with each type in a typename_array by applying a functor.
/// </summary>
/// <typeparam name="array_type">The typename array containing the types to process.</typeparam>
/// <typeparam name="functor_template">The functor template that extracts a value from each type.</typeparam>
/// <typeparam name="return_type">The type of the summed result.</typeparam>
template<typename array_type, template<typename> class functor_template, typename return_type>
struct sum {
private:
/// <summary>
/// Base helper structure for summing values.
/// Provides the final sum when recursion is complete.
/// </summary>
/// <typeparam name="helper_array_type">Array or remaining portion being processed.</typeparam>
/// <typeparam name="helper_functor_template">The functor template applied to each type.</typeparam>
template<typename helper_array_type, template<typename> class helper_functor_template>
struct sum_helper {
/// <summary>
/// The value for an empty array (base case).
/// </summary>
static constexpr return_type new_value{ 0 };
};
/// <summary>
/// Specialization for when the array contains a single type.
/// Extracts the value from that type using the functor.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">The single type in the array.</typeparam>
/// <typeparam name="helper_functor_template">The functor template applied to the type.</typeparam>
template<template<typename> class array_template, typename value_type, template<typename> class helper_functor_template>
struct sum_helper<array_template<value_type>, helper_functor_template> {
/// <summary>
/// The value extracted from the single type.
/// </summary>
static constexpr return_type new_value = helper_functor_template<value_type>::value;
};
/// <summary>
/// Specialization for when the array contains multiple types.
/// Applies the functor to the first type and recursively processes the rest.
/// </summary>
/// <typeparam name="array_template">The template of the array.</typeparam>
/// <typeparam name="value_type">The current type being processed.</typeparam>
/// <typeparam name="other_types">Remaining types in the array.</typeparam>
/// <typeparam name="helper_functor_template">The functor template applied to each type.</typeparam>
template<template<typename...> class array_template, typename value_type, typename... other_types, template<typename> class helper_functor_template>
struct sum_helper<array_template<value_type, other_types...>, helper_functor_template> {
/// <summary>
/// The sum of the value from the current type plus the sum of values from remaining types.
/// </summary>
static constexpr decltype(auto) new_value = helper_functor_template<value_type>::value + sum_helper<array_template<other_types...>, helper_functor_template>::new_value;
};
public:
/// <summary>
/// The total sum of values extracted from all types in the array.
/// </summary>
static constexpr decltype(auto) new_value = sum_helper<array_type, functor_template>::new_value;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_SUM_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_SYMBOLS_TO_INT_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_SYMBOLS_TO_INT_H
#include "base.hpp"
#include "get.hpp"
#include "erase.hpp"
#include "value-wrapper.hpp"
#include "static-pow.hpp"
/// <summary>
/// Converts a sequence of symbol types into an integer value.
/// Handles negative numbers by checking if the first symbol is a minus sign.
/// </summary>
/// <typeparam name="symbols_types">The sequence of symbol types to convert to an integer.</typeparam>
template<typename... symbols_types>
struct symbols_to_int {
private:
/// <summary>
/// Helper structure for the recursive conversion of symbols to integer.
/// </summary>
/// <typeparam name="helper_symbols_types">Symbol types being processed.</typeparam>
template<typename... helper_symbols_types>
struct symbols_to_int_helper;
/// <summary>
/// Recursive specialization that processes one symbol at a time.
/// Multiplies the current symbol's value by the appropriate power of 10 based on position.
/// </summary>
/// <typeparam name="symbol_type">Current symbol being processed.</typeparam>
/// <typeparam name="helper_symbols_types">Remaining symbols to process.</typeparam>
template<typename symbol_type, typename... helper_symbols_types>
struct symbols_to_int_helper<symbol_type, helper_symbols_types...> {
/// <summary>
/// Converts the current digit and adds it to the recursively processed remainder.
/// </summary>
static constexpr typename_array_size_type result = ((symbol_type::get_value - '0') * static_pow<10, sizeof...(helper_symbols_types)>::result) + symbols_to_int_helper<helper_symbols_types...>::result;
static_assert(symbol_type::get_value >= '0' && symbol_type::get_value <= '9', "All symbols must be digits (0-9).");
};
/// <summary>
/// Base case specialization for the last symbol in the sequence.
/// </summary>
/// <typeparam name="symbol_type">The last symbol to process.</typeparam>
template<typename symbol_type>
struct symbols_to_int_helper<symbol_type> {
/// <summary>
/// Converts the last digit to its integer value.
/// </summary>
static constexpr typename_array_size_type result = (symbol_type::get_value - '0');
static_assert(symbol_type::get_value >= '0' && symbol_type::get_value <= '9', "All symbols must be digits (0-9).");
};
/// <summary>
/// The first symbol in the sequence, used to check for negative numbers.
/// </summary>
using first_symbol_type = typename get<0, typename_array<symbols_types...>>::value;
/// <summary>
/// Creates a reduced symbol type which:
/// 1. Removes the minus sign if present
/// 2. Includes a multiplier (-1 for negative numbers, 1 for positive)
/// </summary>
using reduced_symbols_type = std::conditional_t<
first_symbol_type::get_value == '-',
typename_array<typename erase<0, typename_array<symbols_types...>>::new_array, value_wrapper<-1>>,
typename_array<typename_array<symbols_types...>, value_wrapper<1>>
>;
public:
/// <summary>
/// The final integer result after converting the symbol sequence.
/// Accounts for sign by multiplying the absolute value by the sign multiplier.
/// </summary>
static constexpr typename_array_size_type result = get<0, reduced_symbols_type>::value::template acquire<symbols_to_int_helper>::result * get<1, reduced_symbols_type>::value::get_value;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_SYMBOLS_TO_INT_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_TYPENAME_BINDER_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_TYPENAME_BINDER_H
#include "base.hpp"
#include "replace.hpp"
#include "insert.hpp"
#include "find.hpp"
#include "left-to-right.hpp"
#include "get.hpp"
/// <summary>
/// A placeholder type used to mark positions where types should be inserted.
/// </summary>
/// <typeparam name="index">The index of the placeholder for reference.</typeparam>
template<typename_array_size_type index>
struct binder_placeholder {
static constexpr typename_array_size_type get_index = index;
};
/// <summary>
/// A template binder that allows for flexible creation of templates with placeholder substitution.
/// Enables the creation of templates where types are inserted at specific marked positions.
/// </summary>
/// <typeparam name="target_template">The template class to be instantiated after binding.</typeparam>
/// <typeparam name="other_types">Initial types that may contain placeholders.</typeparam>
template<template<typename...> class target_template, typename... other_types>
struct typename_binder {
private:
/// <summary>
/// Helper for dispatching between replacement and insertion operations.
/// Used when a placeholder is found at a specific index.
/// </summary>
/// <typeparam name="index">The index where the placeholder was found.</typeparam>
/// <typeparam name="array_type">The array being processed.</typeparam>
/// <typeparam name="value_type">The value to insert or replace with.</typeparam>
template<typename_array_size_type index, typename array_type, typename value_type>
struct dispatch {
/// <summary>
/// The array after replacement of the placeholder at the specified index.
/// </summary>
using value = typename replace<index, array_type, value_type>::new_array;
};
/// <summary>
/// Specialization for when no placeholder is found (npos).
/// In this case, append the value to the end of the array.
/// </summary>
/// <typeparam name="array_type">The array being processed.</typeparam>
/// <typeparam name="value_type">The value to append.</typeparam>
template<typename array_type, typename value_type>
struct dispatch<npos, array_type, value_type> {
/// <summary>
/// The array after appending the value to the end.
/// Notice that elements are added in the order they appear in "additional_other".
/// That's why we need to use sizeof... (other_types).
/// </summary>
using value = typename insert<sizeof... (other_types), array_type, value_type>::new_array;
};
/// <summary>
/// Recursive helper for binding placeholders to actual types.
/// Processes each placeholder by finding and replacing it with the corresponding type.
/// </summary>
/// <typeparam name="index">Current placeholder index being processed.</typeparam>
/// <typeparam name="end">Last placeholder index to process.</typeparam>
/// <typeparam name="array_type">Array containing the types to be bound.</typeparam>
template<typename_array_size_type index, typename_array_size_type end, typename array_type>
struct bind_helper {
/// <summary>
/// Recursively process the next placeholder.
/// </summary>
using temporary = typename bind_helper<index + 1, end, array_type>::bind;
/// <summary>
/// Find and replace the current placeholder with its corresponding type.
/// </summary>
using bind = typename dispatch<
find<temporary, binder_placeholder<index>>::index,
temporary,
typename get<index, array_type>::value
>::value;
};
/// <summary>
/// Base case for bind_helper recursion - processes the final placeholder.
/// </summary>
/// <typeparam name="end">Index of the final placeholder.</typeparam>
/// <typeparam name="array_type">Array containing the types to be bound.</typeparam>
template<typename_array_size_type end, typename array_type>
struct bind_helper<end, end, array_type> {
/// <summary>
/// Process the final placeholder directly using the initial template.
/// </summary>
using bind = typename dispatch<
find<typename_array<other_types...>, binder_placeholder<end>>::index,
typename_array<other_types...>,
typename get<end, array_type>::value
>::value;
};
public:
/// <summary>
/// Binds the placeholders in the template with the provided types.
/// This creates a new template instance with placeholders replaced by actual types.
/// </summary>
/// <typeparam name="additional_other">The types to bind to the placeholders.</typeparam>
template<typename... additional_other>
using bind = typename bind_helper<
0,
typename_array<additional_other...>::size - 1,
typename_array<additional_other...>
>::bind::template acquire<target_template>;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_TYPENAME_BINDER_H
#ifndef TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_UNIQUE_ADD_H
#define TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_UNIQUE_ADD_H
#include "base.hpp"
#include "insert.hpp"
#include "find.hpp"
/// <summary>
/// Adds a new type to a typename_array only if it doesn't already exist in the array.
/// </summary>
/// <typeparam name="index">The position at which to insert the new type if needed.</typeparam>
/// <typeparam name="array_type">The typename array to potentially modify.</typeparam>
/// <typeparam name="new_value_type">The new type to add if not already present.</typeparam>
template<typename_array_size_type index, typename array_type, typename new_value_type>
struct unique_add {
private:
/// <summary>
/// Base helper structure for the unique_add operation.
/// </summary>
/// <typeparam name="found">The index where the type was found, or npos if not found.</typeparam>
/// <typeparam name="helper_array_type">The array being processed.</typeparam>
/// <typeparam name="helper_new_value_type">The type to potentially add.</typeparam>
template<typename_array_size_type found, typename helper_array_type, typename helper_new_value_type>
struct unique_add_helper {
/// <summary>
/// When the type is already found in the array, return the original array unchanged.
/// </summary>
using value = helper_array_type;
};
/// <summary>
/// Specialization for when the type is not found in the array.
/// </summary>
/// <typeparam name="helper_array_type">The array being processed.</typeparam>
/// <typeparam name="helper_new_value_type">The type to add.</typeparam>
template<typename helper_array_type, typename helper_new_value_type>
struct unique_add_helper<npos, helper_array_type, helper_new_value_type> {
/// <summary>
/// When the type is not found, insert it at the specified index.
/// </summary>
using value = typename insert<index, helper_array_type, helper_new_value_type>::new_array;
};
public:
/// <summary>
/// The resulting array after the unique add operation.
/// Contains the new type only if it wasn't already present.
/// </summary>
using new_array = typename unique_add_helper<find<array_type, new_value_type>::index, array_type, new_value_type>::value;
};
#endif // TYPENAME_ARRAY_TYPENAME_ARRAY_PRIMITIVES_UNIQUE_ADD_H
#ifndef TYPENAME_ARRAY_VALUE_H
#define TYPENAME_ARRAY_VALUE_H
#include "base.hpp"
/// <summary>
/// Wraps a compile-time value of any type in a type context.
/// This allows non-type template parameters to be used in typename arrays.
/// </summary>
/// <typeparam name="value">The compile-time value to wrap in a type.</typeparam>
template<auto value>
struct value_wrapper {
/// <summary>
/// The wrapped value, accessible as a static constant.
/// </summary>
static constexpr decltype(value) get_value = value;
};
#endif // TYPENAME_ARRAY_VALUE_H