#include #include #include #include #include #include #include TEST_CASE("forward_like", "[utility]") { STATIC_REQUIRE(std::is_same_v, float &&>); STATIC_REQUIRE( std::is_same_v, float const &&>); STATIC_REQUIRE( std::is_same_v, float &&>); STATIC_REQUIRE(std::is_same_v, float const &&>); STATIC_REQUIRE(std::is_same_v, float &>); STATIC_REQUIRE(std::is_same_v, float const &>); } TEST_CASE("as_unsigned (changed)", "[utility]") { STATIC_REQUIRE(std::is_same_v); STATIC_REQUIRE(std::is_same_v); STATIC_REQUIRE(std::is_same_v); STATIC_REQUIRE(std::is_same_v); STATIC_REQUIRE(stdx::as_unsigned(std::int8_t{17}) == 17); } TEMPLATE_TEST_CASE("as_unsigned (unchanged)", "[utility]", std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t) { STATIC_REQUIRE( std::is_same_v); STATIC_REQUIRE(stdx::as_unsigned(TestType{17}) == 17); } TEST_CASE("as_signed (changed)", "[utility]") { STATIC_REQUIRE( std::is_same_v); STATIC_REQUIRE(std::is_same_v); STATIC_REQUIRE(std::is_same_v); STATIC_REQUIRE(std::is_same_v); STATIC_REQUIRE(stdx::as_signed(std::uint8_t{17}) == 17); } TEMPLATE_TEST_CASE("as_signed (unchanged)", "[utility]", std::int8_t, std::int16_t, std::int32_t, std::int64_t) { STATIC_REQUIRE( std::is_same_v); STATIC_REQUIRE(stdx::as_signed(TestType{17}) == 17); } TEMPLATE_TEST_CASE("sized in (uint8_t zero/one/two case)", "[utility]", std::uint16_t, std::uint32_t, std::uint64_t) { STATIC_REQUIRE(stdx::sized{0}.in() == 0); STATIC_REQUIRE(stdx::sized{1}.in() == 1); STATIC_REQUIRE(stdx::sized{2}.in() == 1); } TEMPLATE_TEST_CASE("sized in (uint16_t zero/one/two case)", "[utility]", std::uint32_t, std::uint64_t) { STATIC_REQUIRE(stdx::sized{0}.in() == 0); STATIC_REQUIRE(stdx::sized{1}.in() == 1); STATIC_REQUIRE(stdx::sized{2}.in() == 1); } TEMPLATE_TEST_CASE("sized in (uint32_t zero/one/two case)", "[utility]", std::uint64_t) { STATIC_REQUIRE(stdx::sized{0}.in() == 0); STATIC_REQUIRE(stdx::sized{1}.in() == 1); STATIC_REQUIRE(stdx::sized{2}.in() == 1); } TEMPLATE_TEST_CASE("sized in (same type)", "[utility]", std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t) { STATIC_REQUIRE(stdx::sized{3}.template in() == 3); } TEMPLATE_TEST_CASE("sized in (exact case)", "[utility]", std::uint16_t, std::uint32_t, std::uint64_t) { STATIC_REQUIRE( stdx::sized{3 * sizeof(TestType)}.in() == 3); } TEMPLATE_TEST_CASE("sized in defaults to bytes", "[utility]", std::uint16_t, std::uint32_t, std::uint64_t) { STATIC_REQUIRE(stdx::sized{3}.in() == 3 * sizeof(TestType)); } TEMPLATE_TEST_CASE("sized in (downsize)", "[utility]", std::uint8_t, std::uint16_t, std::uint32_t) { STATIC_REQUIRE(stdx::sized{3}.in() == 3 * sizeof(std::uint64_t) / sizeof(TestType)); } TEST_CASE("sized in (upsize uint8_t)", "[utility]") { STATIC_REQUIRE(stdx::sized{3}.in() == 2); STATIC_REQUIRE(stdx::sized{17}.in() == 9); STATIC_REQUIRE(stdx::sized{5}.in() == 2); STATIC_REQUIRE(stdx::sized{17}.in() == 5); STATIC_REQUIRE(stdx::sized{9}.in() == 2); STATIC_REQUIRE(stdx::sized{17}.in() == 3); } TEST_CASE("sized in (upsize uint16_t)", "[utility]") { STATIC_REQUIRE(stdx::sized{3}.in() == 2); STATIC_REQUIRE(stdx::sized{17}.in() == 9); STATIC_REQUIRE(stdx::sized{5}.in() == 2); STATIC_REQUIRE(stdx::sized{17}.in() == 5); } TEST_CASE("sized in (upsize uint32_t)", "[utility]") { STATIC_REQUIRE(stdx::sized{3}.in() == 2); STATIC_REQUIRE(stdx::sized{17}.in() == 9); } TEST_CASE("sized aliases", "[utility]") { STATIC_REQUIRE(stdx::sized8{1}.in() == 1); STATIC_REQUIRE(stdx::sized16{1}.in() == 1); STATIC_REQUIRE(stdx::sized32{1}.in() == 1); STATIC_REQUIRE(stdx::sized64{1}.in() == 1); } TEST_CASE("sized in (downsize not divisible)", "[utility]") { using T = std::array; STATIC_REQUIRE(sizeof(T) == 3); STATIC_REQUIRE(stdx::sized{2}.in() == 3); } TEST_CASE("sized in (upsize not divisible)", "[utility]") { using T = std::array; STATIC_REQUIRE(sizeof(T) == 3); STATIC_REQUIRE(stdx::sized{3}.in() == 3); } TEST_CASE("sized in (downsize, mod > 1)", "[utility]") { using T = std::array; using U = std::array; STATIC_REQUIRE(stdx::sized{1}.in() == 2); } TEST_CASE("sized in (upsize, mod > 1)", "[utility]") { using T = std::array; using U = std::array; STATIC_REQUIRE(stdx::sized{2}.in() == 2); } TEST_CASE("terse size conversion with UDLs", "[utility]") { using namespace stdx::literals; STATIC_REQUIRE(1_z8->z8 == 1); STATIC_REQUIRE(2_z8->z16 == 1); STATIC_REQUIRE(4_z8->z32 == 1); STATIC_REQUIRE(8_z8->z64 == 1); STATIC_REQUIRE(1_z16->z8 == 2); STATIC_REQUIRE(1_z32->z8 == 4); STATIC_REQUIRE(1_z64->z8 == 8); STATIC_REQUIRE(1_z64->in == 4); STATIC_REQUIRE(1_z64->in == 2); } TEST_CASE("CX_VALUE structural value", "[utility]") { auto x = CX_VALUE(42); STATIC_REQUIRE(x() == 42); auto y = CX_VALUE(17, 42); STATIC_REQUIRE(y() == 42); } TEST_CASE("CX_VALUE non-structural value", "[utility]") { auto x = CX_VALUE(std::string_view{"Hello"}); STATIC_REQUIRE(x() == std::string_view{"Hello"}); } TEST_CASE("CX_VALUE type", "[utility]") { auto x = CX_VALUE(int); STATIC_REQUIRE(std::is_same_v>); auto y = CX_VALUE(std::pair); STATIC_REQUIRE(std::is_same_v>>); } namespace { template constexpr auto cx_value_test_nttp() { return CX_VALUE(S); } template constexpr auto cx_value_test_type() { return CX_VALUE(T); } } // namespace TEST_CASE("CX_VALUE on NTTP", "[utility]") { auto x = cx_value_test_nttp<42>(); STATIC_REQUIRE(x() == 42); } TEST_CASE("CX_VALUE on type template argument", "[utility]") { auto x = cx_value_test_type(); STATIC_REQUIRE(std::is_same_v>); } namespace { struct alignas(16) over_aligned {}; } // namespace TEST_CASE("is_aligned_with (integral)", "[utility]") { STATIC_REQUIRE(stdx::is_aligned_with(0b1111)); STATIC_REQUIRE(stdx::is_aligned_with(0b1110)); STATIC_REQUIRE(not stdx::is_aligned_with(0b1111)); STATIC_REQUIRE(stdx::is_aligned_with(0b1100)); STATIC_REQUIRE(not stdx::is_aligned_with(0b1110)); STATIC_REQUIRE(stdx::is_aligned_with(0b1000)); STATIC_REQUIRE(not stdx::is_aligned_with(0b1100)); STATIC_REQUIRE(stdx::is_aligned_with(0b1'0000)); STATIC_REQUIRE(not stdx::is_aligned_with(0b1000)); } TEST_CASE("is_aligned_with (pointer)", "[utility]") { std::int32_t i; auto p = &i; auto pc = reinterpret_cast(p); ++pc; CHECK(stdx::is_aligned_with(pc)); CHECK(not stdx::is_aligned_with(pc)); CHECK(stdx::is_aligned_with(p)); CHECK(stdx::is_aligned_with(p)); CHECK(stdx::is_aligned_with(p)); } #if __cplusplus >= 202002L TEST_CASE("ct (integral)", "[utility]") { constexpr auto vs = stdx::ct<42>(); STATIC_REQUIRE( std::is_same_v const>); constexpr auto vu = stdx::ct<42u>(); STATIC_REQUIRE( std::is_same_v const>); } TEST_CASE("ct (integral constant)", "[utility]") { constexpr auto vs = stdx::ct{}>(); STATIC_REQUIRE( std::is_same_v const>); } TEST_CASE("ct (bool)", "[utility]") { constexpr auto v = stdx::ct(); STATIC_REQUIRE(std::is_same_v const>); } TEST_CASE("ct (char)", "[utility]") { constexpr auto v = stdx::ct<'A'>(); STATIC_REQUIRE( std::is_same_v const>); } namespace { enum struct E { A, B, C }; } TEST_CASE("ct (enum)", "[utility]") { constexpr auto v = stdx::ct(); STATIC_REQUIRE( std::is_same_v const>); } TEST_CASE("ct (type)", "[utility]") { constexpr auto v = stdx::ct(); STATIC_REQUIRE(std::is_same_v const>); } TEST_CASE("is_ct", "[utility]") { constexpr auto x1 = stdx::ct<42>(); STATIC_REQUIRE(stdx::is_ct_v); constexpr auto x2 = stdx::ct(); STATIC_REQUIRE(stdx::is_ct_v); } TEST_CASE("CT_WRAP", "[utility]") { auto x1 = 17; STATIC_REQUIRE(std::is_same_v); CHECK(CT_WRAP(x1) == 17); auto x2 = stdx::ct<17>(); STATIC_REQUIRE( std::is_same_v>); STATIC_REQUIRE(CT_WRAP(x2).value == 17); auto const x3 = 17; STATIC_REQUIRE( std::is_same_v>); STATIC_REQUIRE(CT_WRAP(x3).value == 17); constexpr static auto x4 = 17; STATIC_REQUIRE( std::is_same_v>); STATIC_REQUIRE(CT_WRAP(x4).value == 17); []() { STATIC_REQUIRE(std::is_same_v>); STATIC_REQUIRE(CT_WRAP(X).value == 17); }.template operator()<17>(); } TEST_CASE("CX_WRAP integer runtime arg", "[utility]") { auto x = 17; STATIC_REQUIRE(std::is_same_v); CHECK(CX_WRAP(x) == 17); } TEST_CASE("CX_WRAP string_view runtime arg", "[utility]") { auto x = std::string_view{"hello"}; STATIC_REQUIRE(std::is_same_v); 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); 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); 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); STATIC_REQUIRE(CX_WRAP(x)() == 17); } TEST_CASE("CX_WRAP constexpr integral type", "[utility]") { constexpr auto x = 17; STATIC_REQUIRE(stdx::is_cx_value_v); STATIC_REQUIRE(CX_WRAP(x)() == 17); } TEST_CASE("CX_WRAP constexpr non-structural type", "[utility]") { constexpr static auto x = std::string_view{"hello"}; STATIC_REQUIRE(stdx::is_cx_value_v); STATIC_REQUIRE(CX_WRAP(x)() == std::string_view{"hello"}); } TEST_CASE("CX_WRAP integer literal", "[utility]") { STATIC_REQUIRE(stdx::is_cx_value_v); STATIC_REQUIRE(CX_WRAP(17)() == 17); } TEST_CASE("CX_WRAP string literal", "[utility]") { STATIC_REQUIRE(stdx::is_cx_value_v); STATIC_REQUIRE(CX_WRAP("hello")() == std::string_view{"hello"}); } TEST_CASE("CX_WRAP existing CX_VALUE", "[utility]") { auto x = CX_VALUE(17); STATIC_REQUIRE(stdx::is_cx_value_v); STATIC_REQUIRE(CX_WRAP(x)() == 17); } TEST_CASE("CX_WRAP template argument", "[utility]") { [] { STATIC_REQUIRE(stdx::is_cx_value_v); STATIC_REQUIRE(CX_WRAP(x)() == 17); }.template operator()<17>(); } TEST_CASE("CX_WRAP type argument", "[utility]") { STATIC_REQUIRE( std::is_same_v>); } TEST_CASE("CX_WRAP empty type argument", "[utility]") { using X = std::integral_constant; STATIC_REQUIRE( std::is_same_v>); } TEST_CASE("CX_WRAP integral_constant arg", "[utility]") { auto x = std::integral_constant{}; STATIC_REQUIRE(std::is_same_v); CHECK(CX_WRAP(x)() == 17); } #ifdef __clang__ namespace { struct expression_test { auto f(int x) -> int { return x; } }; } // namespace TEST_CASE("CX_WRAP non-constexpr expression", "[utility]") { auto x = 17; STATIC_REQUIRE( std::is_same_v); CHECK(CX_WRAP(expression_test{}.f(x)) == 17); } #endif #endif STDX_PRAGMA(diagnostic push) #ifdef __clang__ STDX_PRAGMA(diagnostic ignored "-Wunknown-warning-option") STDX_PRAGMA(diagnostic ignored "-Wc++26-extensions") #endif #if __cpp_structured_bindings >= 202411L namespace { template constexpr auto sum() { auto [... Is] = stdx::make_index_sequence{}; constexpr auto sum = (0 + ... + decltype(Is)::value); return sum; } } // namespace TEST_CASE("destructurable integer_sequence", "[utility]") { STATIC_CHECK(sum<4>() == 6); } #endif STDX_PRAGMA(diagnostic pop)