Skip to content

Commit 8c700bb

Browse files
elbenomjcaisse-intel
authored andcommitted
✨ Add operator+ for format_result conversion to ct_string
Problem: - It's verbose to explicitly convert a `format_result` to a `ct_string`. - Docs for `format_result` and `ct_string` are missing some uses, and the use of `ct`. Solution: - Add unary `operator+` for that. - Improve docs for string things.
1 parent b8f5d37 commit 8c700bb

File tree

5 files changed

+55
-1
lines changed

5 files changed

+55
-1
lines changed

docs/ct_format.adoc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,20 @@ If there are no runtime arguments, the result is a `format_result` with an empty
3333
auto s = stdx::ct_format<"Hello {} {}">(CX_VALUE(42), CX_VALUE(17));
3434
// s is stdx::format_result{"Hello 42 17"_ctst, stdx::tuple{}}
3535
----
36-
...and a `format_result` like this without an runtime arguments is implicitly convertible back to a `ct_string`:
36+
37+
...and a `format_result` like this without an runtime arguments is implicitly convertible back
38+
to a `ct_string`, or explicitly convertible using unary `operator+`:
3739
[source,cpp]
3840
----
3941
template <stdx::ct_string S> auto f() { ... };
4042
4143
f<stdx::ct_format<"Hello {}">(CX_VALUE(42))>(); // equivalent to f<"Hello 42">()
44+
+stdx::ct_format<"Hello {}">(CX_VALUE(42)); // equivalent to stdx::ct_string{"Hello 42"}
4245
----
4346

47+
NOTE: Using `operator+` on a `format_result` that has a non-empty tuple of
48+
runtime arguments is a compilation error.
49+
4450
Types and compile-time enumeration values are stringified thus:
4551
[source,cpp]
4652
----

docs/ct_string.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ However, for interfacing with legacy functions, a null terminator can be useful.
8585
See https://github.com/intel/compile-time-init-build/tree/main/include/sc[cib
8686
documentation] for details about the cib string constant class.
8787

88+
=== `cts_t`
89+
8890
Sometimes it is useful to wrap a `ct_string` in a type to preserve compile-time
8991
properties. For this, there is `cts_t` and a corresponding user-defined literal.
9092
[source,cpp]

docs/utility.adoc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,34 @@ auto x = 1729; // int
1515
auto y = stdx::as_unsigned(x); // unsigned int
1616
----
1717

18+
=== `ct`
19+
20+
`ct` is a function template that produces a
21+
https://en.cppreference.com/w/cpp/types/integral_constant.html[`std::integral_constant`]
22+
from a compile-time integral or enumeration type:
23+
24+
[source,cpp]
25+
----
26+
constexpr auto x = stdx::ct<42>(); // std::integral_constant<int, 42>{}
27+
28+
enum struct E { A, B, C };
29+
constexpr auto y = stdx::ct<E::A>(); // std::integral_constant<E, E::A>{}
30+
----
31+
32+
Or, when given a type, it produces a `stdx::type_identity`:
33+
34+
[source,cpp]
35+
----
36+
constexpr auto z = stdx::ct<int>(); // stdx::type_identity<int>{}
37+
----
38+
39+
Or, when given a string literal, it produces a xref:ct_string.adoc#_cts_t[`stdx::cts_t`]:
40+
41+
[source,cpp]
42+
----
43+
constexpr auto s = stdx::ct<"Hello">(); // stdx::cts_t<"Hello">{}
44+
----
45+
1846
=== `CX_VALUE`
1947

2048
`CX_VALUE` is a macro that wraps its argument in a constexpr callable, which can

include/stdx/ct_format.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ template <typename Str, typename Args> struct format_result {
3232
[[no_unique_address]] Str str;
3333
[[no_unique_address]] Args args{};
3434

35+
friend constexpr auto operator+(format_result const &fr)
36+
requires(decltype(ct_string_convertible())::value)
37+
{
38+
return ct_string{fr.str.value};
39+
}
40+
41+
friend constexpr auto operator+(format_result const &) {
42+
static_assert(decltype(ct_string_convertible())::value,
43+
"Unary operator+ can only be used on a format_result "
44+
"without any runtime arguments");
45+
}
46+
3547
private:
3648
friend constexpr auto operator==(format_result const &,
3749
format_result const &) -> bool = default;

test/ct_format.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ TEST_CASE("empty format_result can implicitly convert to ct_string",
160160
STATIC_REQUIRE(conversion_success<stdx::ct_format<"Hello">()>);
161161
}
162162

163+
TEST_CASE("empty format_result can explicitly convert to ct_string",
164+
"[ct_format]") {
165+
using namespace std::string_view_literals;
166+
STATIC_REQUIRE(+stdx::ct_format<"Hello">() == "Hello"_cts);
167+
}
168+
163169
namespace {
164170
template <typename T, T...> struct string_constant {
165171
private:

0 commit comments

Comments
 (0)