Skip to content

Commit 3023efe

Browse files
authored
Merge pull request #253 from elbeno/fix-cx-wrap
🐛 Fix `CX_WRAP` for empty types
2 parents b9ed877 + 0a6b530 commit 3023efe

File tree

2 files changed

+36
-27
lines changed

2 files changed

+36
-27
lines changed

include/stdx/utility.hpp

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -260,23 +260,25 @@ template <typename T> constexpr auto is_ct_v<T const> = is_ct_v<T>;
260260

261261
#if __cplusplus >= 202002L
262262

263-
#define CT_WRAP(X) \
263+
#define CT_WRAP(...) \
264264
[&](auto f) { \
265265
if constexpr (::stdx::is_ct_v<decltype(f())>) { \
266266
return f(); \
267267
} else if constexpr (requires { \
268-
::stdx::ct<[&]() constexpr { return X; }()>; \
268+
::stdx::ct<[&]() constexpr { \
269+
return __VA_ARGS__; \
270+
}()>; \
269271
}) { \
270-
return ::stdx::ct<[&]() constexpr { return X; }()>(); \
272+
return ::stdx::ct<[&]() constexpr { return __VA_ARGS__; }()>(); \
271273
} else { \
272274
return f(); \
273275
} \
274-
}([&] { return X; })
276+
}([&] { return __VA_ARGS__; })
275277

276278
#ifdef __clang__
277-
#define CX_DETECT(X) \
279+
#define CX_DETECT(...) \
278280
std::is_empty_v<decltype([&] { \
279-
return (X) + ::stdx::cxv_detail::type_val{}; \
281+
return (__VA_ARGS__) + ::stdx::cxv_detail::type_val{}; \
280282
})>
281283
#else
282284
namespace stdx {
@@ -285,42 +287,42 @@ template <auto> constexpr auto cx_detect0() {}
285287
constexpr auto cx_detect1(auto) { return 0; }
286288
} // namespace v1
287289
} // namespace stdx
288-
#define CX_DETECT(X) \
290+
#define CX_DETECT(...) \
289291
requires { \
290292
::stdx::cx_detect0<::stdx::cx_detect1( \
291-
(X) + ::stdx::cxv_detail::type_val{})>; \
293+
(__VA_ARGS__) + ::stdx::cxv_detail::type_val{})>; \
292294
}
293295
#endif
294296

295-
#define CX_WRAP(X) \
296-
[&](auto f) { \
297+
#define CX_WRAP(...) \
298+
[&]([[maybe_unused]] auto f) { \
297299
STDX_PRAGMA(diagnostic push) \
298300
STDX_PRAGMA(diagnostic ignored "-Wold-style-cast") \
299-
if constexpr (::stdx::is_cx_value_v< \
300-
std::invoke_result_t<decltype(f)>> or \
301-
std::is_empty_v<std::invoke_result_t<decltype(f)>>) { \
301+
if constexpr (decltype(::stdx::cxv_detail::is_type< \
302+
::stdx::cxv_detail::from_any( \
303+
__VA_ARGS__)>())::value) { \
304+
return ::stdx::overload{ \
305+
::stdx::cxv_detail::cx_base{}, [&] { \
306+
return ::stdx::type_identity< \
307+
decltype(::stdx::cxv_detail::type_of< \
308+
::stdx::cxv_detail::from_any( \
309+
__VA_ARGS__)>())>{}; \
310+
}}; \
311+
} else if constexpr (::stdx::is_cx_value_v< \
312+
std::invoke_result_t<decltype(f)>> or \
313+
std::is_empty_v< \
314+
std::invoke_result_t<decltype(f)>>) { \
302315
return f(); \
303-
} else if constexpr (CX_DETECT(X)) { \
304-
if constexpr (decltype(::stdx::cxv_detail::is_type< \
305-
::stdx::cxv_detail::from_any( \
306-
X)>())::value) { \
307-
return ::stdx::overload{ \
308-
::stdx::cxv_detail::cx_base{}, [&] { \
309-
return ::stdx::type_identity< \
310-
decltype(::stdx::cxv_detail::type_of< \
311-
::stdx::cxv_detail::from_any(X)>())>{}; \
312-
}}; \
313-
} else { \
314-
return ::stdx::overload{::stdx::cxv_detail::cx_base{}, f}; \
315-
} \
316+
} else if constexpr (CX_DETECT(__VA_ARGS__)) { \
317+
return ::stdx::overload{::stdx::cxv_detail::cx_base{}, f}; \
316318
} else { \
317319
return f(); \
318320
} \
319321
STDX_PRAGMA(diagnostic pop) \
320322
}([&] { \
321323
STDX_PRAGMA(diagnostic push) \
322324
STDX_PRAGMA(diagnostic ignored "-Wold-style-cast") \
323-
return (X) + ::stdx::cxv_detail::type_val{}; \
325+
return (__VA_ARGS__) + ::stdx::cxv_detail::type_val{}; \
324326
STDX_PRAGMA(diagnostic pop) \
325327
})
326328

test/utility.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,13 @@ TEST_CASE("CX_WRAP type argument", "[utility]") {
364364
std::is_same_v<decltype(CX_WRAP(int)()), stdx::type_identity<int>>);
365365
}
366366

367+
TEST_CASE("CX_WRAP empty type argument", "[utility]") {
368+
using X = std::integral_constant<int, 17>;
369+
STATIC_REQUIRE(stdx::is_cx_value_v<decltype(CX_WRAP(X))>);
370+
STATIC_REQUIRE(
371+
std::is_same_v<decltype(CX_WRAP(X)()), stdx::type_identity<X>>);
372+
}
373+
367374
TEST_CASE("CX_WRAP integral_constant arg", "[utility]") {
368375
auto x = std::integral_constant<int, 17>{};
369376
STATIC_REQUIRE(std::is_same_v<decltype(CX_WRAP(x)), decltype(x)>);

0 commit comments

Comments
 (0)