Skip to content

Commit 8e2f948

Browse files
authored
Merge pull request #262 from elbeno/fix-cx-detect
🐛 Fix constexpr detection
2 parents ff96a19 + c7742dd commit 8e2f948

File tree

2 files changed

+36
-18
lines changed

2 files changed

+36
-18
lines changed

include/stdx/utility.hpp

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -277,26 +277,23 @@ template <typename T> constexpr auto is_ct_v<T const> = is_ct_v<T>;
277277
}([&]() constexpr { return __VA_ARGS__; })
278278
#endif
279279

280-
#ifndef CX_DETECT
281-
#ifdef __clang__
282-
#define CX_DETECT(...) \
283-
std::is_empty_v<decltype([&] { \
284-
return (__VA_ARGS__) + ::stdx::cxv_detail::type_val{}; \
285-
})>
286-
#else
287280
namespace stdx {
288281
inline namespace v1 {
289-
template <auto> constexpr auto cx_detect0() {}
290-
constexpr auto cx_detect1(auto) { return 0; }
282+
namespace cxv_detail {
283+
template <auto> constexpr auto cx_sfinae = std::true_type{};
284+
285+
#ifdef __clang__
286+
auto cx_detect(auto f) -> decltype(cx_sfinae<from_any{f()}>);
287+
auto cx_detect(...) -> std::false_type;
288+
#else
289+
auto cx_detect(auto f) {
290+
constexpr auto b = requires { cx_sfinae<from_any{f()}>; };
291+
return std::bool_constant<b>{};
292+
}
293+
#endif
294+
} // namespace cxv_detail
291295
} // namespace v1
292296
} // namespace stdx
293-
#define CX_DETECT(...) \
294-
requires { \
295-
::stdx::cx_detect0<::stdx::cx_detect1( \
296-
(__VA_ARGS__) + ::stdx::cxv_detail::type_val{})>; \
297-
}
298-
#endif
299-
#endif
300297

301298
#ifndef CX_WRAP
302299
#define CX_WRAP(...) \
@@ -310,7 +307,8 @@ constexpr auto cx_detect1(auto) { return 0; }
310307
std::is_empty_v< \
311308
std::invoke_result_t<decltype(f)>>) { \
312309
return f(); \
313-
} else if constexpr (CX_DETECT(__VA_ARGS__)) { \
310+
} else if constexpr (decltype(::stdx::cxv_detail::cx_detect( \
311+
f))::value) { \
314312
return ::stdx::overload{::stdx::cxv_detail::cx_base{}, f}; \
315313
} else { \
316314
return f(); \

test/utility.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,26 @@ TEST_CASE("CX_WRAP string_view runtime arg", "[utility]") {
317317
CHECK(CX_WRAP(x) == std::string_view{"hello"});
318318
}
319319

320+
namespace {
321+
auto at_init_time() { return 17; }
322+
auto nc_var = at_init_time();
323+
} // namespace
324+
325+
TEST_CASE("CX_WRAP static runtime arg", "[utility]") {
326+
STATIC_REQUIRE(std::is_same_v<decltype(CX_WRAP(nc_var)), decltype(nc_var)>);
327+
CHECK(CX_WRAP(nc_var) == 17);
328+
}
329+
330+
namespace {
331+
constexpr auto at_compile_time() { return 17; }
332+
constexpr auto c_var = at_compile_time();
333+
} // namespace
334+
335+
TEST_CASE("CX_WRAP static constexpr arg", "[utility]") {
336+
STATIC_REQUIRE(stdx::is_cx_value_v<decltype(CX_WRAP(c_var))>);
337+
STATIC_REQUIRE(CX_WRAP(c_var)() == 17);
338+
}
339+
320340
TEST_CASE("CX_WRAP const integral type", "[utility]") {
321341
auto const x = 17;
322342
STATIC_REQUIRE(stdx::is_cx_value_v<decltype(CX_WRAP(x))>);
@@ -378,7 +398,7 @@ TEST_CASE("CX_WRAP integral_constant arg", "[utility]") {
378398
#ifdef __clang__
379399
namespace {
380400
struct expression_test {
381-
int f(int x) { return x; }
401+
auto f(int x) -> int { return x; }
382402
};
383403
} // namespace
384404

0 commit comments

Comments
 (0)