From fe4003b0d2494ceee5146df75fb5ee96da977117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Ba=C4=87?= Date: Tue, 5 Mar 2024 20:33:21 +0100 Subject: [PATCH] is_stream_insertable_v and reserved identifier fix --- example/expect.cpp | 19 ++++++++++++++++ include/boost/ut.hpp | 54 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/example/expect.cpp b/example/expect.cpp index 48f02e91..cd74e345 100644 --- a/example/expect.cpp +++ b/example/expect.cpp @@ -14,9 +14,11 @@ constexpr auto sum = [](auto... args) { return (0 + ... + args); }; +struct dummy_struct{}; int main() { using namespace boost::ut; + "operators"_test = [] { expect(0_i == sum()); expect(2_i != sum(1, 2)); @@ -39,6 +41,23 @@ int main() { }; "eq/neq/gt/ge/lt/le"_test = [] { + // type_traits::is_stream_insertable_v constraint check + + static_assert( type_traits::is_stream_insertable_v); + static_assert( !type_traits::is_stream_insertable_v); + + // it seems it produces nice error information + // leaving this as easy way to check failing compilation in case of doubt + // expect(eq(dummy_struct{}, sum(40, 2))); + // gcc + // expect.cpp:46:14: error: no matching function for call to ‘eq(dummy_struct, int)’ + // 46 | expect(eq(dummy_struct{}, sum(40, 2))); + // | ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // clang + // expect.cpp:51:12: error: no matching function for call to 'eq' + // 51 | expect(eq(dummy_struct{}, sum(40, 2))); + // | ^~ + expect(eq(42, sum(40, 2))); expect(neq(1, 2)); expect(eq(sum(1), 1) and neq(sum(1, 2), 2)); diff --git a/include/boost/ut.hpp b/include/boost/ut.hpp index 3aa586de..941dffcb 100644 --- a/include/boost/ut.hpp +++ b/include/boost/ut.hpp @@ -105,7 +105,7 @@ export import std; #include #endif -struct _unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct { +struct unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_ { }; BOOST_UT_EXPORT @@ -298,15 +298,15 @@ template inline constexpr const std::string_view raw_type_name = get_template_function_name_use_decay_type< - _unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct>(); + unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_>(); inline constexpr const std::size_t raw_length = raw_type_name.length(); inline constexpr const std::string_view need_name = #if defined(_MSC_VER) and not defined(__clang__) "struct " - "_unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct"; + "unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_"; #else - "_unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct"; + "unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_"; #endif inline constexpr const std::size_t need_length = need_name.length(); static_assert(need_length <= raw_length, @@ -1325,6 +1325,17 @@ struct aborts_ : op { namespace type_traits { template inline constexpr auto is_op_v = __is_base_of(detail::op, T); + +template +struct is_stream_insertable : std::false_type {}; + +template +struct is_stream_insertable< + T, std::void_t() + << detail::get(std::declval()))>> + : std::true_type {}; +template +inline constexpr bool is_stream_insertable_v = is_stream_insertable::value; } // namespace type_traits struct colors { @@ -3050,32 +3061,53 @@ struct suite { template [[maybe_unused]] constexpr auto type = detail::type_(); -template +template and + type_traits::is_stream_insertable_v>> [[nodiscard]] constexpr auto eq(const TLhs& lhs, const TRhs& rhs) { return detail::eq_{lhs, rhs}; } -template +template and + type_traits::is_stream_insertable_v>> [[nodiscard]] constexpr auto approx(const TLhs& lhs, const TRhs& rhs, const TEpsilon& epsilon) { return detail::approx_{lhs, rhs, epsilon}; } -template +template and + type_traits::is_stream_insertable_v>> [[nodiscard]] constexpr auto neq(const TLhs& lhs, const TRhs& rhs) { return detail::neq_{lhs, rhs}; } -template +template and + type_traits::is_stream_insertable_v>> [[nodiscard]] constexpr auto gt(const TLhs& lhs, const TRhs& rhs) { return detail::gt_{lhs, rhs}; } -template +template and + type_traits::is_stream_insertable_v>> [[nodiscard]] constexpr auto ge(const TLhs& lhs, const TRhs& rhs) { return detail::ge_{lhs, rhs}; } -template +template and + type_traits::is_stream_insertable_v>> [[nodiscard]] constexpr auto lt(const TLhs& lhs, const TRhs& rhs) { return detail::lt_{lhs, rhs}; } -template +template and + type_traits::is_stream_insertable_v>> [[nodiscard]] constexpr auto le(const TLhs& lhs, const TRhs& rhs) { return detail::le_{lhs, rhs}; }