Skip to content

Commit 8e54700

Browse files
committed
✨ Add CT_WRAP
Problem: - It is useful to have a macro that wraps a potentially-`constexpr`-usable value in `stdx::ct` when possible, to preserve its `constexpr` properties. Solution: - Add `CT_WRAP` that does this. Notes: - See intel/compile-time-init-build#743 for some parts of this in CIB; this part probably belongs in stdx.
1 parent effadd4 commit 8e54700

File tree

4 files changed

+77
-0
lines changed

4 files changed

+77
-0
lines changed

include/stdx/ct_string.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ template <std::size_t N> struct ct_helper<ct_string<N>>;
160160

161161
template <ct_string Value> CONSTEVAL auto ct() { return cts_t<Value>{}; }
162162

163+
template <ct_string Value> constexpr auto is_ct_v<cts_t<Value>> = true;
164+
163165
inline namespace literals {
164166
inline namespace ct_string_literals {
165167
template <ct_string S> CONSTEVAL_UDL auto operator""_cts() { return S; }

include/stdx/utility.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ template <detail::ct_helper Value> CONSTEVAL auto ct() {
209209
}
210210
template <typename T> CONSTEVAL auto ct() { return type_identity<T>{}; }
211211

212+
template <typename> constexpr auto is_ct_v = false;
213+
template <typename T, T V>
214+
constexpr auto is_ct_v<std::integral_constant<T, V>> = true;
215+
template <typename T> constexpr auto is_ct_v<type_identity<T>> = true;
216+
template <typename T> constexpr auto is_ct_v<T const> = is_ct_v<T>;
217+
212218
#endif
213219
} // namespace v1
214220
} // namespace stdx
@@ -244,5 +250,22 @@ template <typename T> CONSTEVAL auto ct() { return type_identity<T>{}; }
244250
}()
245251
#endif
246252

253+
#if __cplusplus >= 202002L
254+
255+
#define CT_WRAP(X) \
256+
[&](auto f) CONSTEVAL { \
257+
if constexpr (::stdx::is_ct_v<decltype(f())>) { \
258+
return f(); \
259+
} else if constexpr (requires { \
260+
::stdx::ct<[&]() constexpr { return X; }()>; \
261+
}) { \
262+
return ::stdx::ct<[&]() constexpr { return X; }()>(); \
263+
} else { \
264+
return f(); \
265+
} \
266+
}([&] { return X; })
267+
268+
#endif
269+
247270
// NOLINTEND(cppcoreguidelines-macro-usage)
248271
// NOLINTEND(modernize-use-constraints)

test/ct_string.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,26 @@ TEST_CASE("ct (ct_string)", "[ct_string]") {
150150
constexpr auto v2 = stdx::ct<"Hello"_cts>();
151151
STATIC_REQUIRE(v2 == "Hello"_ctst);
152152
}
153+
154+
TEST_CASE("is_ct (ct_string)", "[ct_string]") {
155+
using namespace stdx::ct_string_literals;
156+
constexpr auto v1 = stdx::ct<"Hello">();
157+
STATIC_REQUIRE(stdx::is_ct_v<decltype(v1)>);
158+
}
159+
160+
TEST_CASE("CT_WRAP", "[ct_string]") {
161+
using namespace stdx::ct_string_literals;
162+
auto x1 = "hello"_cts;
163+
STATIC_REQUIRE(std::is_same_v<decltype(CT_WRAP(x1)), stdx::ct_string<6>>);
164+
165+
auto x2 = "hello"_ctst;
166+
STATIC_REQUIRE(std::is_same_v<decltype(CT_WRAP(x2)), stdx::cts_t<"hello">>);
167+
168+
constexpr static auto x3 = "hello"_cts;
169+
STATIC_REQUIRE(std::is_same_v<decltype(CT_WRAP(x3)), stdx::cts_t<"hello">>);
170+
171+
[]<stdx::ct_string X>() {
172+
STATIC_REQUIRE(
173+
std::is_same_v<decltype(CT_WRAP(X)), stdx::cts_t<"hello">>);
174+
}.template operator()<"hello">();
175+
}

test/utility.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,4 +271,33 @@ TEST_CASE("ct (type)", "[utility]") {
271271
STATIC_REQUIRE(std::is_same_v<decltype(v), stdx::type_identity<int> const>);
272272
}
273273

274+
TEST_CASE("is_ct", "[utility]") {
275+
constexpr auto x1 = stdx::ct<42>();
276+
STATIC_REQUIRE(stdx::is_ct_v<decltype(x1)>);
277+
constexpr auto x2 = stdx::ct<int>();
278+
STATIC_REQUIRE(stdx::is_ct_v<decltype(x2)>);
279+
}
280+
281+
TEST_CASE("CT_WRAP", "[utility]") {
282+
auto x1 = 42;
283+
STATIC_REQUIRE(std::is_same_v<decltype(CT_WRAP(x1)), int>);
284+
285+
auto x2 = stdx::ct<42>();
286+
STATIC_REQUIRE(
287+
std::is_same_v<decltype(CT_WRAP(x2)), std::integral_constant<int, 42>>);
288+
289+
auto const x3 = 42;
290+
STATIC_REQUIRE(
291+
std::is_same_v<decltype(CT_WRAP(x3)), std::integral_constant<int, 42>>);
292+
293+
constexpr static auto x4 = 42;
294+
STATIC_REQUIRE(
295+
std::is_same_v<decltype(CT_WRAP(x4)), std::integral_constant<int, 42>>);
296+
297+
[]<auto X>() {
298+
STATIC_REQUIRE(std::is_same_v<decltype(CT_WRAP(X)),
299+
std::integral_constant<int, 42>>);
300+
}.template operator()<42>();
301+
}
302+
274303
#endif

0 commit comments

Comments
 (0)