Skip to content

Commit eba2c71

Browse files
arturbackris-jusiak
authored andcommitted
is_stream_insertable_v and reserved identifier fix
1 parent 9873e7f commit eba2c71

File tree

2 files changed

+62
-11
lines changed

2 files changed

+62
-11
lines changed

example/expect.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
constexpr auto sum = [](auto... args) { return (0 + ... + args); };
1616

17+
struct dummy_struct{};
1718
int main() {
1819
using namespace boost::ut;
1920

21+
2022
"operators"_test = [] {
2123
expect(0_i == sum());
2224
expect(2_i != sum(1, 2));
@@ -39,6 +41,23 @@ int main() {
3941
};
4042

4143
"eq/neq/gt/ge/lt/le"_test = [] {
44+
// type_traits::is_stream_insertable_v constraint check
45+
46+
static_assert( type_traits::is_stream_insertable_v<int>);
47+
static_assert( !type_traits::is_stream_insertable_v<dummy_struct>);
48+
49+
// it seems it produces nice error information
50+
// leaving this as easy way to check failing compilation in case of doubt
51+
// expect(eq(dummy_struct{}, sum(40, 2)));
52+
// gcc
53+
// expect.cpp:46:14: error: no matching function for call to ‘eq(dummy_struct, int)’
54+
// 46 | expect(eq(dummy_struct{}, sum(40, 2)));
55+
// | ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
56+
// clang
57+
// expect.cpp:51:12: error: no matching function for call to 'eq'
58+
// 51 | expect(eq(dummy_struct{}, sum(40, 2)));
59+
// | ^~
60+
4261
expect(eq(42, sum(40, 2)));
4362
expect(neq(1, 2));
4463
expect(eq(sum(1), 1) and neq(sum(1, 2), 2));

include/boost/ut.hpp

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export import std;
105105
#include <source_location>
106106
#endif
107107

108-
struct _unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct {
108+
struct unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_ {
109109
};
110110

111111
BOOST_UT_EXPORT
@@ -298,15 +298,15 @@ template <typename TargetType>
298298

299299
inline constexpr const std::string_view raw_type_name =
300300
get_template_function_name_use_decay_type<
301-
_unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct>();
301+
unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_>();
302302

303303
inline constexpr const std::size_t raw_length = raw_type_name.length();
304304
inline constexpr const std::string_view need_name =
305305
#if defined(_MSC_VER) and not defined(__clang__)
306306
"struct "
307-
"_unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct";
307+
"unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_";
308308
#else
309-
"_unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct";
309+
"unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_";
310310
#endif
311311
inline constexpr const std::size_t need_length = need_name.length();
312312
static_assert(need_length <= raw_length,
@@ -1325,6 +1325,17 @@ struct aborts_ : op {
13251325
namespace type_traits {
13261326
template <class T>
13271327
inline constexpr auto is_op_v = __is_base_of(detail::op, T);
1328+
1329+
template <typename T, typename = void>
1330+
struct is_stream_insertable : std::false_type {};
1331+
1332+
template <typename T>
1333+
struct is_stream_insertable<
1334+
T, std::void_t<decltype(std::declval<std::ostream&>()
1335+
<< detail::get(std::declval<T>()))>>
1336+
: std::true_type {};
1337+
template <typename T>
1338+
inline constexpr bool is_stream_insertable_v = is_stream_insertable<T>::value;
13281339
} // namespace type_traits
13291340

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

3053-
template <class TLhs, class TRhs>
3064+
template <class TLhs, class TRhs,
3065+
typename = type_traits::requires_t<
3066+
type_traits::is_stream_insertable_v<TLhs> and
3067+
type_traits::is_stream_insertable_v<TRhs>>>
30543068
[[nodiscard]] constexpr auto eq(const TLhs& lhs, const TRhs& rhs) {
30553069
return detail::eq_{lhs, rhs};
30563070
}
3057-
template <class TLhs, class TRhs, class TEpsilon>
3071+
template <class TLhs, class TRhs, class TEpsilon,
3072+
typename = type_traits::requires_t<
3073+
type_traits::is_stream_insertable_v<TLhs> and
3074+
type_traits::is_stream_insertable_v<TRhs>>>
30583075
[[nodiscard]] constexpr auto approx(const TLhs& lhs, const TRhs& rhs,
30593076
const TEpsilon& epsilon) {
30603077
return detail::approx_{lhs, rhs, epsilon};
30613078
}
3062-
template <class TLhs, class TRhs>
3079+
template <class TLhs, class TRhs,
3080+
typename = type_traits::requires_t<
3081+
type_traits::is_stream_insertable_v<TLhs> and
3082+
type_traits::is_stream_insertable_v<TRhs>>>
30633083
[[nodiscard]] constexpr auto neq(const TLhs& lhs, const TRhs& rhs) {
30643084
return detail::neq_{lhs, rhs};
30653085
}
3066-
template <class TLhs, class TRhs>
3086+
template <class TLhs, class TRhs,
3087+
typename = type_traits::requires_t<
3088+
type_traits::is_stream_insertable_v<TLhs> and
3089+
type_traits::is_stream_insertable_v<TRhs>>>
30673090
[[nodiscard]] constexpr auto gt(const TLhs& lhs, const TRhs& rhs) {
30683091
return detail::gt_{lhs, rhs};
30693092
}
3070-
template <class TLhs, class TRhs>
3093+
template <class TLhs, class TRhs,
3094+
typename = type_traits::requires_t<
3095+
type_traits::is_stream_insertable_v<TLhs> and
3096+
type_traits::is_stream_insertable_v<TRhs>>>
30713097
[[nodiscard]] constexpr auto ge(const TLhs& lhs, const TRhs& rhs) {
30723098
return detail::ge_{lhs, rhs};
30733099
}
3074-
template <class TLhs, class TRhs>
3100+
template <class TLhs, class TRhs,
3101+
typename = type_traits::requires_t<
3102+
type_traits::is_stream_insertable_v<TLhs> and
3103+
type_traits::is_stream_insertable_v<TRhs>>>
30753104
[[nodiscard]] constexpr auto lt(const TLhs& lhs, const TRhs& rhs) {
30763105
return detail::lt_{lhs, rhs};
30773106
}
3078-
template <class TLhs, class TRhs>
3107+
template <class TLhs, class TRhs,
3108+
typename = type_traits::requires_t<
3109+
type_traits::is_stream_insertable_v<TLhs> and
3110+
type_traits::is_stream_insertable_v<TRhs>>>
30793111
[[nodiscard]] constexpr auto le(const TLhs& lhs, const TRhs& rhs) {
30803112
return detail::le_{lhs, rhs};
30813113
}

0 commit comments

Comments
 (0)