Operate strings in constant context.
- Copyright
- MIT License.
Basic usages
Create constant strings
constexpr auto str = cstr("hello world!");
Main header file for the constant string type.
String type that can be evaluated in a constant context.
Definition: conststr.hpp:657
or use user-defined string literal (recommended):
constexpr auto str = "hello world!"_cs;
Define string literal suffix.
Definition: conststr.hpp:1953
The above include
s and using
s are omitted in subsequent examples.
Print strings
The operator<<(std::ostream &, const cstr &)
has been overloaded, so:
constexpr auto str = "hello world!"_cs;
std::cout << str << std::endl;
Compare strings
The conststr::cstr
instances are compared in lexicographic order:
static_assert("hello"_cs > "hell"_cs);
Concatenate strings
constexpr auto hello = "hello"_cs;
constexpr auto world = "world"_cs;
constexpr auto msg = hello + ' ' + world + '!';
constexpr auto msg2 = hello.flatten(" "_cs, world, "!"_cs);
constexpr auto msg3 = flatten(hello, " "_cs, world, "!"_cs);
constexpr auto flatten(const First &first, const Str &...strs)
Flatten multiple strings of different lengths.
Definition: conststr.hpp:1933
Operate strings
- Note
- In order to maintain the uniformity of APIs, all methods that operate on strings do not modify the string itself, but return the modified string.
constexpr auto str = "hello world!"_cs;
constexpr auto newstr = str.uppercase()
.pop()
.erase(4)
.erase(8)
.append('?');
Check the document page of conststr::cstr
to learn more operating methods.
If you really want to modify the original string, std::transform
and functions in the namespace conststr::charutils
may be helpful:
#include <algorithm>
constexpr auto fun() {
auto str = "hello world!"_cs;
std::transform(str.begin(), str.end(), str.begin(),
charutils::replace<'o', 'O'>);
std::transform(str.begin(), str.begin() + 2, str.begin(),
charutils::toupper<char>);
return str;
}
Some constexpr character operating functions.
Definition: conststr.hpp:345
Convert to view
- Warning
cstr
can be implicitly converted to its view
type, but the implicit conversion of a temporary cstr
r-values may result in dangling pointers.
Whenever you need to obtain string view or internal pointer from a cstr
r-value, store it to a variable first.
constexpr auto str = func_returns_cstr();
constexpr view_type sv = str;
The view type of cstr
defaults to std::basic_string_view<T>
. You can choose different view types through the following methods:
#include <span>
constexpr auto s1 =
cstr(
"hello world!", sv<std::span<const char>>);
constexpr auto s2 = "hello world!"_cs.with_view<std::span<const char>>();
constexpr auto sv
String view type selector. Assist in type deduction of cstr.
Definition: conststr.hpp:643
Work with limited reflection
Thanks to the introduction of structured binding, we can implement compile-time reflection of aggregate types based on some tricks.
You can include the header file reflect.hpp
to use conststr::cstr
with reflection, basically it is a reimplementation of glaze based on conststr::cstr
.
In order to get reflection you need to use default-constructible aggregate types, Roughly, this means that the type:
- no user-declared or inherited constructors,
- no virtual/private/protected base classes,
- all members are public,
- no virtual member functions,
- default-constructible,
- no member of reference type (but member of
std::reference_wrapper
with default initializer is allowed).
For example:
struct MyStruct {
int number;
double decimal;
std::string name;
};
Then you can get the name of its members via reflect::name_of
, get the type of its members via reflect::type_of
/reflect::type_of_member
, or get the reference to object's member via reflect::member_of
like the following example:
struct MyStruct {
int number;
double decimal;
std::string name;
};
int main() {
std::cout << reflect::number_of_members<MyStruct> << std::endl;
std::cout << reflect::name_of<MyStruct, 0> << std::endl;
std::cout << reflect::name_of<MyStruct, 1> << std::endl;
std::cout << reflect::name_of<MyStruct, 2> << std::endl;
MyStruct s;
decltype(auto) numref = reflect::member_of<0>(s);
numref = 100;
std::cout << s.number << std::endl;
decltype(auto) nameref = reflect::member_of<"name">(s);
nameref += "hello world";
std::cout << s.name << std::endl;
return 0;
}
type_of< T, index_of< T, Name > > type_of_member
Get the type of the member by its name.
Definition: reflect.hpp:1908
std::remove_cvref_t< std::tuple_element_t< N, decltype(to_tuple(fake_obj< T >))> > type_of
Type of N-th member of a default-constructible aggregate type T.
Definition: reflect.hpp:1745
Header file of comiple-time reflection support.