Skip to content

Commit

Permalink
is_stream_insertable_v and reserved identifier fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Artur Bać committed Mar 5, 2024
1 parent 9873e7f commit fe4003b
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 11 deletions.
19 changes: 19 additions & 0 deletions example/expect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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<int>);
static_assert( !type_traits::is_stream_insertable_v<dummy_struct>);

// 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));
Expand Down
54 changes: 43 additions & 11 deletions include/boost/ut.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export import std;
#include <source_location>
#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
Expand Down Expand Up @@ -298,15 +298,15 @@ template <typename TargetType>

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,
Expand Down Expand Up @@ -1325,6 +1325,17 @@ struct aborts_ : op {
namespace type_traits {
template <class T>
inline constexpr auto is_op_v = __is_base_of(detail::op, T);

template <typename T, typename = void>
struct is_stream_insertable : std::false_type {};

template <typename T>
struct is_stream_insertable<
T, std::void_t<decltype(std::declval<std::ostream&>()
<< detail::get(std::declval<T>()))>>
: std::true_type {};
template <typename T>
inline constexpr bool is_stream_insertable_v = is_stream_insertable<T>::value;
} // namespace type_traits

struct colors {
Expand Down Expand Up @@ -3050,32 +3061,53 @@ struct suite {
template <class T = void>
[[maybe_unused]] constexpr auto type = detail::type_<T>();

template <class TLhs, class TRhs>
template <class TLhs, class TRhs,
typename = type_traits::requires_t<
type_traits::is_stream_insertable_v<TLhs> and
type_traits::is_stream_insertable_v<TRhs>>>
[[nodiscard]] constexpr auto eq(const TLhs& lhs, const TRhs& rhs) {
return detail::eq_{lhs, rhs};
}
template <class TLhs, class TRhs, class TEpsilon>
template <class TLhs, class TRhs, class TEpsilon,
typename = type_traits::requires_t<
type_traits::is_stream_insertable_v<TLhs> and
type_traits::is_stream_insertable_v<TRhs>>>
[[nodiscard]] constexpr auto approx(const TLhs& lhs, const TRhs& rhs,
const TEpsilon& epsilon) {
return detail::approx_{lhs, rhs, epsilon};
}
template <class TLhs, class TRhs>
template <class TLhs, class TRhs,
typename = type_traits::requires_t<
type_traits::is_stream_insertable_v<TLhs> and
type_traits::is_stream_insertable_v<TRhs>>>
[[nodiscard]] constexpr auto neq(const TLhs& lhs, const TRhs& rhs) {
return detail::neq_{lhs, rhs};
}
template <class TLhs, class TRhs>
template <class TLhs, class TRhs,
typename = type_traits::requires_t<
type_traits::is_stream_insertable_v<TLhs> and
type_traits::is_stream_insertable_v<TRhs>>>
[[nodiscard]] constexpr auto gt(const TLhs& lhs, const TRhs& rhs) {
return detail::gt_{lhs, rhs};
}
template <class TLhs, class TRhs>
template <class TLhs, class TRhs,
typename = type_traits::requires_t<
type_traits::is_stream_insertable_v<TLhs> and
type_traits::is_stream_insertable_v<TRhs>>>
[[nodiscard]] constexpr auto ge(const TLhs& lhs, const TRhs& rhs) {
return detail::ge_{lhs, rhs};
}
template <class TLhs, class TRhs>
template <class TLhs, class TRhs,
typename = type_traits::requires_t<
type_traits::is_stream_insertable_v<TLhs> and
type_traits::is_stream_insertable_v<TRhs>>>
[[nodiscard]] constexpr auto lt(const TLhs& lhs, const TRhs& rhs) {
return detail::lt_{lhs, rhs};
}
template <class TLhs, class TRhs>
template <class TLhs, class TRhs,
typename = type_traits::requires_t<
type_traits::is_stream_insertable_v<TLhs> and
type_traits::is_stream_insertable_v<TRhs>>>
[[nodiscard]] constexpr auto le(const TLhs& lhs, const TRhs& rhs) {
return detail::le_{lhs, rhs};
}
Expand Down

0 comments on commit fe4003b

Please sign in to comment.