1414
1515LIBASSERT_BEGIN_NAMESPACE
1616namespace detail {
17+ template <typename T>
18+ inline constexpr bool is_pointer_or_member_pointer = std::is_pointer_v<strip<T>> || std::is_member_pointer_v<strip<T>>;
1719 // Lots of boilerplate
1820 // std:: implementations don't allow two separate types for lhs/rhs
1921 // Note: is this macro potentially bad when it comes to debugging(?)
@@ -168,10 +170,11 @@ namespace detail {
168170 struct expression_decomposer <nothing, nothing, nothing> {
169171 explicit constexpr expression_decomposer () = default;
170172#define LIBASSERT_GEN_BITFIELD_BOILERPLATE (type )\
171- template <typename Delay = type>[[nodiscard]] constexpr auto operator <<(const type& operand)&& {\
173+ template <typename Delay = type>[[nodiscard]] constexpr auto operator <<(type operand)&& {\
172174 return expression_decomposer<Delay, nothing, nothing>(operand);\
173175 }
174176
177+ LIBASSERT_GEN_BITFIELD_BOILERPLATE (bool )
175178 LIBASSERT_GEN_BITFIELD_BOILERPLATE (char )
176179 LIBASSERT_GEN_BITFIELD_BOILERPLATE (signed char )
177180 LIBASSERT_GEN_BITFIELD_BOILERPLATE (unsigned char )
@@ -188,7 +191,7 @@ namespace detail {
188191#undef LIBASSERT_GEN_BITFIELD_BOILERPLATE
189192
190193
191- template <typename O> [[nodiscard]] constexpr auto operator <<(O&& operand) && {
194+ template <typename O,std:: enable_if_t <!std::is_integral_v<strip<O>>, int > = 0 > [[nodiscard]] constexpr auto operator <<(O&& operand) && {
192195 return expression_decomposer<O, nothing, nothing>(std::forward<O>(operand));
193196 }
194197 };
@@ -262,38 +265,36 @@ namespace detail {
262265 // and rvalues as rvalues.
263266 return std::forward<A>(a);
264267 }
265- template <typename Depend = std::remove_reference_t <A>,std::enable_if_t <
266- std::is_member_pointer_v<Depend> || std::is_pointer_v<Depend>,int > = 0
267- >
268- constexpr auto operator ==(decltype (NULL )) &&
268+ template <typename Null,std::enable_if_t <
269+ std::is_integral_v<Null> && is_pointer_or_member_pointer<A>,int > = 0 >
270+ constexpr auto operator ==(Null) &&
269271 {
270272 return expression_decomposer<A, std::nullptr_t , ops::eq>(std::forward<A>(a), nullptr );
271273 }
272274
273- template <typename Depend = A , std::enable_if_t <isa<Depend, decltype ( NULL )>, int > = 0
274- , typename Pointer>
275- constexpr auto operator ==(Pointer* pointer)&&
275+ template <typename Pointer , std::enable_if_t <
276+ is_pointer_or_member_pointer< Pointer> && std::is_integral_v<strip<A>>, int > = 0 >
277+ constexpr auto operator ==(Pointer&& pointer) &&
276278 {
277- return expression_decomposer<std::nullptr_t , Pointer* , ops::eq > (nullptr , pointer);
279+ return expression_decomposer<std::nullptr_t , Pointer, ops::eq > (nullptr , std::forward<Pointer>( pointer) );
278280 }
279281
280- template <typename Depend = std::remove_reference_t <A>, std::enable_if_t <
281- std::is_member_pointer_v<Depend> || std::is_pointer_v<Depend>, int > = 0
282- >
283- constexpr auto operator !=(decltype (NULL ))&&
282+ template <typename Null, std::enable_if_t <std::is_integral_v<Null> && is_pointer_or_member_pointer<A>, int > = 0 >
283+ constexpr auto operator !=(Null) &&
284284 {
285285 return expression_decomposer<A, std::nullptr_t , ops::neq>(std::forward<A>(a), nullptr );
286286 }
287287
288- template <typename Depend = A, std::enable_if_t <isa<Depend, decltype (NULL )>, int > = 0
289- , typename Pointer>
290- constexpr auto operator !=(Pointer* pointer)&&
288+ template <typename Pointer, std::enable_if_t <
289+ is_pointer_or_member_pointer<Pointer> &&
290+ std::is_integral_v<strip<A>>,int > = 0 >
291+ constexpr auto operator !=(Pointer&& pointer) &&
291292 {
292- return expression_decomposer<std::nullptr_t , Pointer* , ops::neq>(nullptr , pointer);
293+ return expression_decomposer<std::nullptr_t , Pointer, ops::neq>(nullptr , std::forward<Pointer>( pointer) );
293294 }
294-
295+
295296 #define LIBASSERT_GEN_OP_BOILERPLATE (functor, op ) \
296- template <typename O> [[nodiscard]] constexpr auto operator op (O&& operand) && { \
297+ template <typename O,std:: enable_if_t <!((std::is_integral_v<strip<O>> && is_pointer_or_member_pointer<A>) || (std::is_integral_v<strip<A>> && is_pointer_or_member_pointer<O>)), int > = 0 > [[nodiscard]] constexpr auto operator op (O&& operand) && { \
297298 return expression_decomposer<A, O, functor>(std::forward<A>(a), std::forward<O>(operand)); \
298299 }
299300 LIBASSERT_DO_GEN_OP_BOILERPLATE
0 commit comments