Skip to content

Commit 856283f

Browse files
committed
🎨 Don't double-wrap an integral_constant with ct
Problem: - Passing an `integral_constant` to `ct` results in a doubly-wrapped `integral_constant`. Solution: - Partially specialize `ct_helper` to deal with this case.
1 parent df5ae34 commit 856283f

File tree

2 files changed

+17
-0
lines changed

2 files changed

+17
-0
lines changed

include/stdx/utility.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,24 @@ constexpr auto is_aligned_with = [](auto v) -> bool {
260260
};
261261

262262
#if __cplusplus >= 202002L
263+
template <typename T>
264+
concept integral_constant_like = requires {
265+
[]<typename Int, Int I>(std::integral_constant<Int, I>) {}(T{});
266+
};
263267

264268
namespace detail {
265269
template <typename T> struct ct_helper {
266270
// NOLINTNEXTLINE(google-explicit-constructor)
267271
CONSTEVAL ct_helper(T t) : value(t) {}
268272
T value;
269273
};
274+
275+
template <integral_constant_like T> struct ct_helper<T> {
276+
// NOLINTNEXTLINE(google-explicit-constructor)
277+
CONSTEVAL ct_helper(T) : value(T::value) {}
278+
typename T::value_type value;
279+
};
280+
270281
template <typename T> ct_helper(T) -> ct_helper<T>;
271282

272283
template <auto> CONSTEVAL auto cx_detect0() {}

test/utility.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,12 @@ TEST_CASE("ct (integral)", "[utility]") {
260260
std::integral_constant<unsigned int, 42> const>);
261261
}
262262

263+
TEST_CASE("ct (integral constant)", "[utility]") {
264+
constexpr auto vs = stdx::ct<std::integral_constant<int, 42>{}>();
265+
STATIC_REQUIRE(
266+
std::is_same_v<decltype(vs), std::integral_constant<int, 42> const>);
267+
}
268+
263269
TEST_CASE("ct (bool)", "[utility]") {
264270
constexpr auto v = stdx::ct<true>();
265271
STATIC_REQUIRE(std::is_same_v<decltype(v), std::bool_constant<true> const>);

0 commit comments

Comments
 (0)