feat(utils/types): compile time string for error types

This commit is contained in:
2026-11-09 13:45:00 -05:00
parent 9f3a2fca44
commit 35e5d5a249
3 changed files with 116 additions and 55 deletions

View File

@@ -5,27 +5,126 @@
#include <string_view>
namespace serif::utils::types {
template<std::size_t N>
struct ctstring {
char data[N]{};
template <std::size_t N>
struct FixedString {
char dataValue[N]{};
constexpr ctstring(const char (&str)[N]) {
std::copy_n(str, N, data);
consteval FixedString(const char (&stringValue)[N]) {
for (std::size_t index = 0; index < N; ++index) {
dataValue[index] = stringValue[index];
}
}
constexpr std::string_view view() const { return {data, N - 1}; }
};
template<std::size_t N>
struct ct_error_string {
char data[289+N]{};
char padding[289]{"NOTE: This error message is generated at compile time. C++ < 26 limits how compile time errors can be formatted, This is the relevant error message not downstream warnings about implicit instantiations of an undefined template. Those are used to force the compiler to display this message"};
constexpr ct_error_string(const char (&str)[N]) {
std::copy_n(str, N, data);
std::copy_n(padding, 289, data+N);
constexpr std::size_t size() const noexcept {
return N - 1;
}
constexpr std::string_view view() const { return {data, N - 1}; }
constexpr const char* data() const noexcept {
return dataValue;
}
constexpr char operator[](const std::size_t index) const noexcept {
return dataValue[index];
}
};
template <std::size_t Capacity>
struct CTString {
std::array<char, Capacity> dataValue{};
std::size_t sizeValue = 0;
constexpr std::size_t size() const noexcept {
return sizeValue;
}
constexpr const char* data() const noexcept {
return dataValue.data();
}
consteval void append(const char character) {
dataValue[sizeValue++] = character;
}
template <std::integral IntegerT>
consteval void append_integer(IntegerT value) {
using UnsignedT = std::make_unsigned_t<IntegerT>;
UnsignedT magnitude;
if constexpr (std::signed_integral<IntegerT>) {
if (value < 0) {
append('-');
magnitude = static_cast<UnsignedT>(-(value + 1)) + 1;
} else {
magnitude = static_cast<UnsignedT>(value);
}
} else {
magnitude = value;
}
char buffer[std::numeric_limits<UnsignedT>::digits10 + 2]{};
std::size_t digitCount = 0;
do {
buffer[digitCount++] = static_cast<char>('0' + magnitude % 10);
magnitude /= 10;
} while (magnitude != 0);
while (digitCount > 0) {
append(buffer[--digitCount]);
}
}
};
template <std::size_t Capacity, typename ArgT>
consteval void append_argument(
CTString<Capacity>& output,
const ArgT& argument
) {
if constexpr (std::integral<ArgT>) {
output.append_integer(argument);
} else {
static_assert(std::integral<ArgT>, "ct_format currently only supports integral arguments");
}
}
template <FixedString Format, std::size_t Capacity, typename ArgT, typename... ArgsT>
consteval void format_impl(
CTString<Capacity>& output,
std::size_t& formatPosition,
const ArgT& argument,
const ArgsT&... args
) {
while (formatPosition < Format.size()) {
if (Format[formatPosition] == '{' && formatPosition + 1 < Format.size() && Format[formatPosition + 1] == '}') {
append_argument(output, argument);
formatPosition += 2;
if constexpr (sizeof...(ArgsT) > 0) {
format_impl<Format>(output, formatPosition, args...);
}
return;
}
output.append(Format[formatPosition]);
++formatPosition;
}
}
template <FixedString Format, std::size_t Capacity = 256, typename... ArgsT>
consteval auto ct_format(const ArgsT&... args) {
CTString<Capacity> output{};
std::size_t formatPosition = 0;
if constexpr (sizeof...(ArgsT) > 0) {
format_impl<Format>(output, formatPosition, args...);
}
while (formatPosition < Format.size()) {
output.append(Format[formatPosition++]);
}
return output;
}
}

View File

@@ -1,7 +0,0 @@
#pragma once
#include "serif/utils/types/tensor/tensor.hpp"
namespace serif::utils::types::backend::mfem {
}

View File

@@ -1,31 +0,0 @@
#pragma once
#include <cstddef>
namespace serif::utils::types {
template <typename T>
struct VectorBase {
using Type = T;
};
template <typename T>
struct DenseMatrixBase {
using Type = T;
};
template <typename T>
struct SparseMatrixBase{
using Type = T;
};
template <typename T, std::size_t Rank>
struct DenseTensorBase {
using Type = T;
static constexpr std::size_t rank = Rank;
};
template <typename T, std::size_t Rank>
struct SparseTensorBase {
using Type = T;
static constexpr std::size_t rank = Rank;
};
}