JH-Toolkit v1.4.1
An engineering-oriented C++20 toolkit with duck-typed concepts, static design, async coroutines, and semantic containers — header-only, RTTI-free, and concurrency-friendly.
Loading...
Searching...
No Matches
jh::meta::t_str< N > Struct Template Referencefinal

Compile-time string wrapper for use as a non-type template parameter (NTTP). More...

#include <jh/metax/t_str.h>

Public Types

using c_hash = jh::meta::c_hash

Public Member Functions

constexpr t_str (const jh::pod::array< char, N > &arr) noexcept
 build from underlying buffer
constexpr t_str (const char(&lit)[N]) noexcept
 Construct from a regular string literal.
constexpr t_str (const char8_t(&lit)[N]) noexcept
 Construct from a char8_t-based string literal (u8"").
constexpr const char * val () const noexcept
 Get a pointer to the stored string.
constexpr std::uint64_t size () const noexcept
 Get the length of the string (excluding null terminator).
constexpr std::string_view view () const noexcept
 Get a std::string_view over the stored string.
constexpr jh::pod::string_view pod_view () const noexcept
 Get a jh::pod::string_view over the stored string.
std::string str () const
 Get a std::string as a copy of the stored string.
constexpr std::uint64_t hash (c_hash hash_method=c_hash::fnv1a64, bool include_null=false) const noexcept
 Compute a constexpr hash of the stored string.
template<std::uint16_t M>
constexpr auto operator+ (const t_str< M > &other) const noexcept
 Concatenate two t_str strings at compile time.
template<std::uint16_t Pos, std::uint16_t Count = npos>
constexpr auto sub () const noexcept
 Extract a substring at compile time.
template<std::uint16_t Pos, std::uint16_t Count = npos>
constexpr std::string_view sub_view () const noexcept
 Obtain a std::string_view over a substring.
template<std::uint16_t Pos, std::uint16_t Count = npos>
constexpr jh::pod::string_view sub_pod_view () const noexcept
 Obtain a jh::pod::string_view over a substring.
constexpr bool is_digit () const noexcept
 Check if all characters are decimal digits (0-9).
constexpr bool is_number () const noexcept
 Check if the string represents a valid decimal number.
constexpr bool is_alpha () const noexcept
 Check if all characters are alphabetic (A-Z, a-z).
constexpr bool is_alnum () const noexcept
 Check if all characters are alphanumeric (letters or digits).
constexpr bool is_ascii () const noexcept
 Check if all characters are 7-bit ASCII.
constexpr bool is_printable_ascii () const noexcept
 Check if all characters are printable 7-bit ASCII.
constexpr bool is_legal () const noexcept
 Check if all characters are valid (printable ASCII or UTF-8).
constexpr bool is_hex () const noexcept
 Check if the string is a valid hexadecimal sequence.
constexpr bool is_base64 () const noexcept
 Check if the string is valid Base64.
constexpr bool is_base64url () const noexcept
 Check if the string is valid Base64URL.
template<bool AllowParent = false>
constexpr bool is_valid_relative_path () const noexcept
 Validate a POSIX-style relative path at compile time.
constexpr auto to_upper () const noexcept
 Convert all alphabetic characters to uppercase (A-Z).
constexpr auto to_lower () const noexcept
 Convert all alphabetic characters to lowercase (a-z).
constexpr auto flip_case () const noexcept
 Toggle the case of all alphabetic characters.
template<std::uint16_t M>
requires (M != N)
constexpr bool operator== (const t_str< M > &) const noexcept
 Equality comparison with another t_str of different size.
constexpr bool operator== (const t_str &) const noexcept=default
 Equality comparison with another t_str of the same size.
constexpr operator jh::pod::array< std::uint8_t, N - 1 > () const noexcept
 Convert the string (excluding the null terminator) to a byte array.
constexpr jh::pod::array< std::uint8_t, N - 1 > to_bytes () const noexcept
 Convert to an immutable byte buffer.

Static Public Member Functions

static constexpr t_str from_bytes (const jh::pod::array< std::uint8_t, N - 1 > &bytes) noexcept
 Construct a t_str<N> from a byte buffer.

Public Attributes

const jh::pod::array< char, N > storage
 Fixed-size storage for the compile-time string (null-terminated).

Static Public Attributes

static constexpr auto npos = static_cast<std::uint16_t>(-1)
 Sentinel value representing "no position" or "until the end".

Friends

template<std::uint16_t M>
struct t_str
 Friendship is required for implementing operator+.

Detailed Description

template<std::uint16_t N>
requires detail::t_str_size_legal<N>
struct jh::meta::t_str< N >

Compile-time string wrapper for use as a non-type template parameter (NTTP).

Template Parameters
NThe size of the string literal including null terminator.

t_str<N> enables string literals to be bound directly as non-type template parameters (NTTP) in C++20. It provides constexpr construction, validation, transformation, concatenation, and hashing of string literals with zero runtime overhead.

Constructor & Destructor Documentation

◆ t_str() [1/2]

template<std::uint16_t N>
jh::meta::t_str< N >::t_str ( const char(&) lit[N])
inlineconstexprnoexcept

Construct from a regular string literal.

This constructor is intentionally implicit. It enables string literals to be passed directly as non-type template parameters (NTTP) without requiring additional wrappers.

Note
A user-defined literal such as "..."_ts cannot be supported due to a fundamental language limitation.
In C++, a user-defined literal operator receives const char* (and a length), but it cannot encode that length as a template argument N.
Since t_str<N> requires the string size (including the null terminator) to be part of the type, the size must be preserved at the type level.
Only a reference to a string literal const char(&)[N] retains the compile-time array bound required for correct template deduction.
Therefore, implicit construction from a string literal is the only fully standard and portable mechanism.

◆ t_str() [2/2]

template<std::uint16_t N>
jh::meta::t_str< N >::t_str ( const char8_t(&) lit[N])
inlineconstexprnoexcept

Construct from a char8_t-based string literal (u8"").

This constructor provides compatibility for platforms or codebases where u8"" string literals yield const char8_t[]. Each element is converted to char for uniform storage.

This is a non-standard compatibility feature — since in most modern platforms, "" literals are already UTF-8 encoded. The intent is only to allow u8"" literals to be used seamlessly as NTTP, consistent with regular string literals.

Member Function Documentation

◆ flip_case()

template<std::uint16_t N>
auto jh::meta::t_str< N >::flip_case ( ) const
inlinenodiscardconstexprnoexcept

Toggle the case of all alphabetic characters.

Returns
A new t_str with each character's case flipped.

◆ from_bytes()

template<std::uint16_t N>
constexpr t_str jh::meta::t_str< N >::from_bytes ( const jh::pod::array< std::uint8_t, N - 1 > & bytes)
inlinestaticnodiscardconstexprnoexcept

Construct a t_str<N> from a byte buffer.

Parameters
bytesA jh::pod::array<std::uint8_t, N - 1> representing a binary buffer.
The buffer does not contain a null terminator.
Returns
A new t_str<N> whose characters are taken directly from bytes, with a null terminator appended internally.
  • This function treats bytes as pure binary data.
  • No validation is performed — any byte value (0-255) is accepted.
  • The resulting t_str is always null-terminated internally, because t_str is semantically a C-string wrapper.
  • This method enables a useful pattern: writing a binary buffer as if it were a string literal, then reconstructing t_str from it.
  • The null terminator added at the end is not part of the returned bytes if converted back using to_bytes().

Example Usage:

jh::meta::t_str<bytes.size() + 1>::from_bytes(bytes);
// Use this form instead of an explicit size, especially when the byte array is deduced with auto.
Compile-time string wrapper for use as a non-type template parameter (NTTP).
Definition t_str.h:109
static constexpr t_str from_bytes(const jh::pod::array< std::uint8_t, N - 1 > &bytes) noexcept
Construct a t_str<N> from a byte buffer.
Definition t_str.h:904
constexpr std::uint64_t size() const noexcept
Get the length of the string (excluding null terminator).
Definition t_str.h:210

◆ hash()

template<std::uint16_t N>
std::uint64_t jh::meta::t_str< N >::hash ( c_hash hash_method = c_hash::fnv1a64,
bool include_null = false ) const
inlinenodiscardconstexprnoexcept

Compute a constexpr hash of the stored string.

Parameters
hash_methodThe hash algorithm to use (default: c_hash::fnv1a64). Supported algorithms:
include_nullIf true, the null terminator is included in the hash computation.
Returns
64-bit non-cryptographic hash value.
Note
All supported algorithms are constexpr-safe and suitable for compile-time use (e.g., as template arguments or static IDs). They are not cryptographically secure.

◆ is_alnum()

template<std::uint16_t N>
bool jh::meta::t_str< N >::is_alnum ( ) const
inlinenodiscardconstexprnoexcept

Check if all characters are alphanumeric (letters or digits).

Returns
true if all characters are alphanumeric, false otherwise.

◆ is_alpha()

template<std::uint16_t N>
bool jh::meta::t_str< N >::is_alpha ( ) const
inlinenodiscardconstexprnoexcept

Check if all characters are alphabetic (A-Z, a-z).

Returns
true if all characters are alphabetic, false otherwise.

◆ is_ascii()

template<std::uint16_t N>
bool jh::meta::t_str< N >::is_ascii ( ) const
inlinenodiscardconstexprnoexcept

Check if all characters are 7-bit ASCII.

Returns
true if all characters are in range 0-127, false otherwise.

◆ is_base64()

template<std::uint16_t N>
bool jh::meta::t_str< N >::is_base64 ( ) const
inlinenodiscardconstexprnoexcept

Check if the string is valid Base64.

Length must be a multiple of 4, padding ('=') allowed at the end.

Returns
true if valid Base64, false otherwise.

◆ is_base64url()

template<std::uint16_t N>
bool jh::meta::t_str< N >::is_base64url ( ) const
inlinenodiscardconstexprnoexcept

Check if the string is valid Base64URL.

'=' padding is optional. If present, length must be a multiple of 4.

Returns
true if valid Base64URL, false otherwise.

◆ is_digit()

template<std::uint16_t N>
bool jh::meta::t_str< N >::is_digit ( ) const
inlinenodiscardconstexprnoexcept

Check if all characters are decimal digits (0-9).

Note
This only checks that each character is a digit. To validate if the whole string represents a number (with optional sign, decimal point, or exponent), use is_number() instead.
Returns
true if all characters are digits, false otherwise.

◆ is_hex()

template<std::uint16_t N>
bool jh::meta::t_str< N >::is_hex ( ) const
inlinenodiscardconstexprnoexcept

Check if the string is a valid hexadecimal sequence.

Length must be even, and all characters must be hex digits.

Returns
true if valid hex string, false otherwise.

◆ is_legal()

template<std::uint16_t N>
bool jh::meta::t_str< N >::is_legal ( ) const
inlinenodiscardconstexprnoexcept

Check if all characters are valid (printable ASCII or UTF-8).

Returns
true if all characters are valid, false otherwise.

◆ is_number()

template<std::uint16_t N>
bool jh::meta::t_str< N >::is_number ( ) const
inlinenodiscardconstexprnoexcept

Check if the string represents a valid decimal number.

Returns
true if the string is a valid number, otherwise false.

Grammar (simplified BNF):

  [ '+' | '-' ] DIGIT+ [ '.' DIGIT+ ] [ ( 'e' | 'E' ) [ '+' | '-' ] DIGIT+ ]

Equivalent regular expression:

  ^[+-]?[0-9]+(.[0-9]+)?([eE][+-]?[0-9]+)?$

Rules:

  • The first character may be '+' or '-'.
  • At least one digit must appear before optional '.' or 'e/E'.
  • If '.' appears, at least one digit must follow (either before or after '.').
  • If 'e' or 'E' appears, it must be followed by an optional sign and at least one digit.
  • Only decimal notation is supported (no hex, octal, binary, or locale-specific formats).

◆ is_printable_ascii()

template<std::uint16_t N>
bool jh::meta::t_str< N >::is_printable_ascii ( ) const
inlinenodiscardconstexprnoexcept

Check if all characters are printable 7-bit ASCII.

Returns
true if all characters are in range 32-126, false otherwise.

Verifies that every character lies within the printable 7-bit ASCII range (decimal 32-126).

Note
Printable ASCII is a strict subset of 7-bit ASCII. Therefore: is_printable_ascii() implies is_ascii()
If this function returns true, calling is_ascii() again is redundant. When used inside a requires clause, do not combine the two checks.
This function only permits ASCII characters. If the intention is to validate fully printable text including multi-byte UTF-8 sequences, use is_legal() instead.
is_legal() performs:
  • UTF-8 structural validation
  • rejection of invalid UTF-8 byte combinations
  • rejection of illegal ASCII control characters

◆ is_valid_relative_path()

template<std::uint16_t N>
template<bool AllowParent = false>
bool jh::meta::t_str< N >::is_valid_relative_path ( ) const
inlinenodiscardconstexprnoexcept

Validate a POSIX-style relative path at compile time.

Warning
This implementation relies on correct C++20 constant evaluation behavior for NTTP-based string types. GCC 13 and earlier versions contain known constexpr/NTTP evaluation defects that may cause incorrect compilation failures.
GCC 14 or later is required. Clang is unaffected.

This function performs strict validation of a POSIX-style relative path. It is intended for project-internal path specifications and is designed to be evaluated at compile time.

Core Constraints

  • Length must be in range [1, 128].
  • Must be a relative path (no leading '/').
  • Only POSIX-style separators ('/') are allowed.
  • No "./" segments.
  • ".." handling:
    • If AllowParent == false → any ".." segment is rejected.
    • If AllowParent == true → leading "../" segments are allowed, but:
      • The entire path cannot consist only of "../".
      • No ".." is permitted once normal path content begins.
  • Allowed characters: [A-Za-z0-9_.-/].
  • Spaces and non-ASCII characters are forbidden.

Compile-Time Enforcement

This function is intended to be used in constant evaluation contexts. It is typically combined with C++20 constraints:

Explicit form (disallow parent paths):

template<jh::meta::TStr Path>
requires(Path.template is_valid_relative_path<false>())
struct Resource {};
constexpr bool is_valid_relative_path() const noexcept
Validate a POSIX-style relative path at compile time.
Definition t_str.h:722

Default form (equivalent to <false>):

template<jh::meta::TStr Path>
requires(Path.is_valid_relative_path())
struct Resource {};

Since AllowParent defaults to false, both forms are strictly equivalent.

Design Rationale

  • Only strict POSIX-style relative paths are accepted to ensure deterministic, platform-neutral behavior.
  • Whitespace and non-ASCII characters are intentionally disallowed. Project-internal relative paths must be explicitly and cleanly designed, avoiding ambiguity and encoding issues.
  • This validator does not perform normalization or filesystem access.

Cross-Platform Note

On Windows or other platforms, path composition should be performed using std::filesystem rather than embedding platform-specific separators:

std::filesystem::path path =
std::filesystem::path(".") / Path.val();

The validated string is treated purely as a logical POSIX-style relative path and may be combined with platform-native paths via std::filesystem.

Template Parameters
AllowParentWhether leading "../" segments are permitted.
Returns
true if the path satisfies all constraints; otherwise false.

◆ operator jh::pod::array< std::uint8_t, N - 1 >()

template<std::uint16_t N>
jh::meta::t_str< N >::operator jh::pod::array< std::uint8_t, N - 1 > ( ) const
inlineexplicitnodiscardconstexprnoexcept

Convert the string (excluding the null terminator) to a byte array.

Returns
A jh::pod::array<std::uint8_t, N - 1> containing the string's raw character bytes, excluding the null terminator.
  • The returned array contains exactly N - 1 bytes — the effective string length.
  • The array does not contain a null terminator, because it represents a binary buffer, not a C-string.
  • This makes the result suitable for binary serialization, hashing, Base64 encoding, and other byte-wise operations.
  • At compile time, values are assigned element-by-element.
  • At runtime, std::memcpy is used for maximum efficiency.

◆ operator+()

template<std::uint16_t N>
template<std::uint16_t M>
auto jh::meta::t_str< N >::operator+ ( const t_str< M > & other) const
inlinenodiscardconstexprnoexcept

Concatenate two t_str strings at compile time.

Template Parameters
MSize (including null terminator) of the right-hand operand.
Parameters
otherAnother t_str<M> to append.
Returns
A new t_str whose size is (N - 1) + (M - 1) + 1, containing the concatenated characters and a null terminator.
  • Performs constexpr-safe concatenation without dynamic allocation.
  • The total size must satisfy t_str_concat_legal (≤ 16 KB).
  • The null terminator of the left string is ignored during concatenation, and a new null terminator is appended at the end.

◆ operator==() [1/2]

template<std::uint16_t N>
bool jh::meta::t_str< N >::operator== ( const t_str< N > & ) const
constexprdefaultnoexcept

Equality comparison with another t_str of the same size.

Parameters
otherThe other t_str<N>.
Returns
true if and only if all characters match (including the null terminator).

This operator is = default, meaning comparison is delegated to the underlying member const jh::pod::array<char, N> storage.

  • Semantically: it is equivalent to comparing all characters in the string one by one.
  • Implementation-wise: since storage is a POD type, the compiler can optimize this into a direct memcmp-style comparison at compile time or runtime.

◆ operator==() [2/2]

template<std::uint16_t N>
template<std::uint16_t M>
requires (M != N)
bool jh::meta::t_str< N >::operator== ( const t_str< M > & ) const
inlineconstexprnoexcept

Equality comparison with another t_str of different size.

Template Parameters
MSize of the other t_str.
Parameters
UnusedThe other string (ignored, since size mismatch short-circuits).
Returns
false always, because string sizes differ.
Note
This overload exists to provide a compile-time fast-path: if N != M, the comparison does not even check characters.

◆ pod_view()

template<std::uint16_t N>
jh::pod::string_view jh::meta::t_str< N >::pod_view ( ) const
inlinenodiscardconstexprnoexcept

Get a jh::pod::string_view over the stored string.

Returns
A pod::string_view referencing the characters (excluding null terminator).

◆ size()

template<std::uint16_t N>
std::uint64_t jh::meta::t_str< N >::size ( ) const
inlinenodiscardconstexprnoexcept

Get the length of the string (excluding null terminator).

Returns
Number of characters before the null terminator.

◆ str()

template<std::uint16_t N>
std::string jh::meta::t_str< N >::str ( ) const
inlinenodiscard

Get a std::string as a copy of the stored string.

Returns
A std::string copying the template string.
Note
This function exists primarily for ergonomic reasons. When interoperating with runtime APIs that require std::string (e.g. concatenation or formatting), it avoids forcing users to repeatedly write:
std::string{S.val()}
std::string{S.view()}

Instead, S.str() provides a concise and explicit conversion entry point.

The function intentionally performs a copy and is meant only for runtime interop — it does not affect the compile-time nature of t_str.

◆ sub()

template<std::uint16_t N>
template<std::uint16_t Pos, std::uint16_t Count = npos>
auto jh::meta::t_str< N >::sub ( ) const
inlinenodiscardconstexprnoexcept

Extract a substring at compile time.

Template Parameters
PosStarting position of the substring.
CountNumber of characters to extract. If set to jh::meta::t_str<N>::npos, the substring extends from Pos to the end of the string.
Returns
A new t_str containing the selected characters followed by a null terminator.
  • Performs substring extraction entirely at compile time.
  • The resulting string size becomes ActualCount + 1 (including the null terminator).
  • The special value Count = npos acts as a sentinel meaning "until the end of the string".
  • Bounds are validated using t_str_sub_legal.
  • No runtime allocation or loops are involved.
Note
The returned object owns its storage, so any views obtained from it remain valid as long as the returned t_str object exists.
Use:
constexpr auto sub_str = s.sub<Pos, Count>();
auto v2 = sub_str.pod_view(); // same for std version .view()
to ensure the substring's storage is preserved for the view. or use:
auto v1 = s.sub_pod_view<Pos, Count>();
// same for std version .sub_view<Pos, Count>();
to get a view directly without creating a new t_str object.
Anything like:
s.sub<Pos, Count>().pod_view() is valid but creates a temporary t_str that may lead to dangling views if not used carefully.

◆ sub_pod_view()

template<std::uint16_t N>
template<std::uint16_t Pos, std::uint16_t Count = npos>
jh::pod::string_view jh::meta::t_str< N >::sub_pod_view ( ) const
inlinenodiscardconstexprnoexcept

Obtain a jh::pod::string_view over a substring.

Template Parameters
PosStarting position of the substring.
CountNumber of characters to expose. If set to jh::meta::t_str<N>::npos, the view extends from Pos to the end of the string.
Returns
A jh::pod::string_view referencing the selected range.
  • Provides the same behavior as sub_view(), but returns a POD-compatible view type.
  • No memory allocation or copying occurs.
  • The substring length is computed at compile time.
  • The special value Count = npos means "until end".
Note
This function is primarily intended for interoperability with APIs expecting jh::pod::string_view.

◆ sub_view()

template<std::uint16_t N>
template<std::uint16_t Pos, std::uint16_t Count = npos>
std::string_view jh::meta::t_str< N >::sub_view ( ) const
inlinenodiscardconstexprnoexcept

Obtain a std::string_view over a substring.

Template Parameters
PosStarting position of the substring.
CountNumber of characters to expose. If set to jh::meta::t_str<N>::npos, the view extends from Pos to the end of the string.
Returns
A std::string_view referencing the selected range.
  • This function does not allocate or copy memory.
  • The returned view references the internal storage of this t_str.
  • The substring length is computed at compile time.
  • The special value Count = npos means "until end".
Warning
The returned view is non-owning and becomes invalid if the source t_str object goes out of scope.

◆ to_bytes()

template<std::uint16_t N>
jh::pod::array< std::uint8_t, N - 1 > jh::meta::t_str< N >::to_bytes ( ) const
inlinenodiscardconstexprnoexcept

Convert to an immutable byte buffer.

Returns
A jh::pod::array<std::uint8_t, N - 1> containing the raw characters of the string (not null-terminated).

This is equivalent to the explicit byte-array conversion operator.

◆ to_lower()

template<std::uint16_t N>
auto jh::meta::t_str< N >::to_lower ( ) const
inlinenodiscardconstexprnoexcept

Convert all alphabetic characters to lowercase (a-z).

Returns
A new t_str with characters transformed to lowercase.

◆ to_upper()

template<std::uint16_t N>
auto jh::meta::t_str< N >::to_upper ( ) const
inlinenodiscardconstexprnoexcept

Convert all alphabetic characters to uppercase (A-Z).

Returns
A new t_str with characters transformed to uppercase.

◆ val()

template<std::uint16_t N>
const char * jh::meta::t_str< N >::val ( ) const
inlinenodiscardconstexprnoexcept

Get a pointer to the stored string.

Returns
Pointer to the first character of the internal string (null-terminated).
Note
The returned pointer comes from storage.data, which is a const char[N]. It decays to const char* on return.

◆ view()

template<std::uint16_t N>
std::string_view jh::meta::t_str< N >::view ( ) const
inlinenodiscardconstexprnoexcept

Get a std::string_view over the stored string.

Returns
A string_view referencing the characters (excluding null terminator).

◆ t_str

template<std::uint16_t N>
template<std::uint16_t M>
friend struct t_str
friend

Friendship is required for implementing operator+.

Template Parameters
MSize of the other string literal.

Different t_str<M> instances must access each other's internal storage to perform constexpr concatenation.


The documentation for this struct was generated from the following file: