Name Mode Size
..
str.hpp 100644 3 kb
README.md
# [`cxx-str`][] A [C++11][] [`std::string`][] [macro][] library. If [C++20][] is avaiable, [`std::format`][] and [`std::source_location`][] may be more appropriate. If [C++23][] is available, [`std::stacktrace`][] may be more appropriate. [`cxx-str`]: https://git.rcrnstn.net/rcrnstn/cxx-str [C++11]: https://en.wikipedia.org/wiki/C++11 [`std::string`]: https://en.cppreference.com/w/cpp/string/basic_string [macro]: https://en.cppreference.com/w/cpp/preprocessor/replace [C++20]: https://en.wikipedia.org/wiki/C++20 [`std::format`]: https://en.cppreference.com/w/cpp/utility/format/format [`std::source_location`]: https://en.cppreference.com/w/cpp/utility/source_location [C++23]: https://en.wikipedia.org/wiki/C++23 [`std::stacktrace`]: https://en.cppreference.com/w/cpp/utility/basic_stacktrace ## Usage Note that macros can result in unintuitive behavior. Looking at the [source][] and [test][] is the best way to understand usage. Throughout, arguments are only evaluated once. When [lambda][]s are defined and immediately called behind the scenes, values are implicitly [capture][]d by reference. The only lambda that implicitly captures by value is `STR_FUNC(VALUE)`. Include the header: ```cpp #include <str.hpp> ``` There are a few different categories of functionality: - Easy access to [`std::ostringstream`][]'s [`operator<<`][] and [`str()`][]. The `VALUE` expressions below can contain several values joined with `<<`. `STR(VALUE)` produces a string. `STR_FUNC(VALUE)` produces a [lambda][], which implicitly [capture][]s by value, and returns a string. Useful for lazy evaluation of costly string operations. For good performance, make sure the standard library can perform Small String Optimization ([SSO][]) (and if used with [`std::function`][], Small Object Optimization ([SOO][])). `STR_JOIN(JOIN, ITERATOR, VALUE, ...)` makes the variable name `ITERATOR` available in the `VALUE` expression, and joins the corresponding non-empty (as interpreted by `STR(VALUE)`) elements of `...` with `JOIN`. `STR_JOIN_INIT(JOIN, ITERATOR, VALUE, TYPE, ...)` forwards to `STR_JOIN(JOIN, ITERATOR, VALUE, ...)`, passing [`std::initializer_list`][]`<TYPE>`[`__VA_ARGS__`][]`)` as the last argument. Notice the lack of braces, they have to be supplied manually. `STR_JOIN_INITSTR(JOIN, ITERATOR, VALUE, ...)` forwards to `STR_JOIN_INIT` with `std::string` as the `TYPE` argument. - Easy access to the stringifying and concatenating [`#` and `##` operators][] to help map constants to strings. `STR_CASE(CASE)` uses `case` and `return` statements: `case (CASE): return (#CASE);`. `STR_COND(VALUE, CASE)` uses the [conditional operator][]: `((VALUE) == (CASE)) ? (#CASE) :`. `STR_INIT(CASE)` uses [list initialization][]: `{(CASE), (#CASE)},`. `STR_ARGS(ARG)` expands to `ARG, #ARG`. `STR_ARGS_PREFIX(PREFIX, ARG)` expands to `PREFIX##ARG, #ARG`. - Easy access to source file and line. `STR_HERE(VALUE)` joins [`__FILE__` and `__LINE__`][] and [`__func__`][] with `":"`, and appends `": "` and the given argument to produce a string. - Easy handling to ([nested][]) [`std::exception`][]s, which contain strings accessible through the [`what()`][] method. `STR_EXCEPTION` can be defined to control what exceptions are thrown by the macros below. If it is not defined, [`std::runtime_error`][] is used. `STR_THROW(VALUE)` [`throw`][]s a `STR_EXCEPTION` initialized with `STR(VALUE)`. `STR_THROW_ERRNO()` calls `STR_THROW` with the argument `std::generic_category().message(errno) << "."`. `STR_RETHROW(VALUE)` calls [`std::terminate`][] if called outside a [`catch`][] block. Otherwise, `STR_THROW`s `VALUE` followed by the [`what()`][] of the current exception (so it is appropriate to include a separator manually) if it is a (derives from) [`std::exception`][], otherwise simply rethrows the current exception. `STR_NESTED_THROW(VALUE)` calls [`std::throw_with_nested`][] on a `STR_EXCEPTION` initialized with `STR(VALUE)`. `STR_NESTED_THROW_ERRNO()` calls `STR_NESTED_THROW` with the argument `std::generic_category().message(errno) << "."`. `STR_NESTED_WHAT(JOIN, EXCEPTION)` joins the strings returned by the (optionally) [nested][] [`std::exception`][]-based `EXCEPTION`'s [`what()`][] methods with `JOIN`, and returns the resulting string. [source]: include/str.hpp [test]: tests/str.cpp [lambda]: https://en.cppreference.com/w/cpp/language/lambda [capture]: https://en.cppreference.com/w/cpp/language/lambda#Lambda_capture [`std::ostringstream`]: https://en.cppreference.com/w/cpp/io/basic_ostringstream [`operator<<`]: https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt [`str()`]: https://en.cppreference.com/w/cpp/io/basic_ostringstream/str [SSO]: https://en.cppreference.com/w/cpp/language/acronyms [`std::function`]: https://en.cppreference.com/w/cpp/utility/functional/function [SOO]: https://en.cppreference.com/w/cpp/language/acronyms [`std::initializer_list`]: https://en.cppreference.com/w/cpp/utility/initializer_list [`__VA_ARGS__`]: https://en.cppreference.com/w/cpp/preprocessor/replace [`#` and `##` operators]: https://en.cppreference.com/w/cpp/preprocessor/replace#.23_and_.23.23_operators [list initialization]: https://en.cppreference.com/w/cpp/language/list_initialization [conditional operator]: https://en.cppreference.com/w/cpp/language/operator_other#Conditional_operator [`__FILE__` and `__LINE__`]: https://en.cppreference.com/w/c/preprocessor/line [`__func__`]: https://en.cppreference.com/w/cpp/language/function#func [`#ifndef`]: https://en.cppreference.com/w/cpp/preprocessor/conditional [`NDEBUG`]: https://en.cppreference.com/w/c/error/assert [nested]: https://en.cppreference.com/w/cpp/error/nested_exception [`std::exception`]: https://en.cppreference.com/w/cpp/error/exception [`what()`]: https://en.cppreference.com/w/cpp/error/exception/what [`std::runtime_error`]: https://en.cppreference.com/w/cpp/error/runtime_error [`throw`]: https://en.cppreference.com/w/cpp/language/throw [`std::terminate`]: https://en.cppreference.com/w/cpp/error/terminate [`catch`]: https://en.cppreference.com/w/cpp/language/try_catch [`std::throw_with_nested`]: https://en.cppreference.com/w/cpp/error/throw_with_nested ## Test output The [test][] outputs: ``` 0x3 0x3 "first", "", "third" first, third first unknown third /path/to/cxx-str/tests/str.cpp:96: Hello from here Failed to do outer: Failed to do inner: Expected this, got that. ``` ## Building See [`BUILDING.md`][]. [`BUILDING.md`]: BUILDING.md ## License Licensed under the [ISC License][] unless otherwise noted, see the [`LICENSE`][] file. [ISC License]: https://choosealicense.com/licenses/isc/ [`LICENSE`]: LICENSE