Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 15 additions & 17 deletions include/stdx/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,26 +277,23 @@ template <typename T> constexpr auto is_ct_v<T const> = is_ct_v<T>;
}([&]() constexpr { return __VA_ARGS__; })
#endif

#ifndef CX_DETECT
#ifdef __clang__
#define CX_DETECT(...) \
std::is_empty_v<decltype([&] { \
return (__VA_ARGS__) + ::stdx::cxv_detail::type_val{}; \
})>
#else
namespace stdx {
inline namespace v1 {
template <auto> constexpr auto cx_detect0() {}
constexpr auto cx_detect1(auto) { return 0; }
namespace cxv_detail {
template <auto> constexpr auto cx_sfinae = std::true_type{};

#ifdef __clang__
auto cx_detect(auto f) -> decltype(cx_sfinae<from_any{f()}>);
auto cx_detect(...) -> std::false_type;
#else
auto cx_detect(auto f) {
constexpr auto b = requires { cx_sfinae<from_any{f()}>; };
return std::bool_constant<b>{};
}
#endif
} // namespace cxv_detail
} // namespace v1
} // namespace stdx
#define CX_DETECT(...) \
requires { \
::stdx::cx_detect0<::stdx::cx_detect1( \
(__VA_ARGS__) + ::stdx::cxv_detail::type_val{})>; \
}
#endif
#endif

#ifndef CX_WRAP
#define CX_WRAP(...) \
Expand All @@ -310,7 +307,8 @@ constexpr auto cx_detect1(auto) { return 0; }
std::is_empty_v< \
std::invoke_result_t<decltype(f)>>) { \
return f(); \
} else if constexpr (CX_DETECT(__VA_ARGS__)) { \
} else if constexpr (decltype(::stdx::cxv_detail::cx_detect( \
f))::value) { \
return ::stdx::overload{::stdx::cxv_detail::cx_base{}, f}; \
} else { \
return f(); \
Expand Down
22 changes: 21 additions & 1 deletion test/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,26 @@ TEST_CASE("CX_WRAP string_view runtime arg", "[utility]") {
CHECK(CX_WRAP(x) == std::string_view{"hello"});
}

namespace {
auto at_init_time() { return 17; }
auto nc_var = at_init_time();
} // namespace

TEST_CASE("CX_WRAP static runtime arg", "[utility]") {
STATIC_REQUIRE(std::is_same_v<decltype(CX_WRAP(nc_var)), decltype(nc_var)>);
CHECK(CX_WRAP(nc_var) == 17);
}

namespace {
constexpr auto at_compile_time() { return 17; }
constexpr auto c_var = at_compile_time();
} // namespace

TEST_CASE("CX_WRAP static constexpr arg", "[utility]") {
STATIC_REQUIRE(stdx::is_cx_value_v<decltype(CX_WRAP(c_var))>);
STATIC_REQUIRE(CX_WRAP(c_var)() == 17);
}

TEST_CASE("CX_WRAP const integral type", "[utility]") {
auto const x = 17;
STATIC_REQUIRE(stdx::is_cx_value_v<decltype(CX_WRAP(x))>);
Expand Down Expand Up @@ -378,7 +398,7 @@ TEST_CASE("CX_WRAP integral_constant arg", "[utility]") {
#ifdef __clang__
namespace {
struct expression_test {
int f(int x) { return x; }
auto f(int x) -> int { return x; }
};
} // namespace

Expand Down