Skip to content

Commit 4ee4b17

Browse files
zhanyongwancopybara-github
authored andcommitted
Allow DistanceFrom() to use user-defined abs() by default.
`std::abs()` doesn't work on custom types. While one can use the 3-argument version of `DistanceFrom()` to specify how to compute the distance, it's not as convenient as defining `abs()` for the custom type once in the type's namespace and then use the 2-argument version. PiperOrigin-RevId: 735741409 Change-Id: If8fb668455eb963a2ccf089f7467c64965a2e7a6
1 parent 0bdccf4 commit 4ee4b17

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

docs/reference/matchers.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Matcher | Description
4242
| `Lt(value)` | `argument < value` |
4343
| `Ne(value)` | `argument != value` |
4444
| `IsFalse()` | `argument` evaluates to `false` in a Boolean context. |
45-
| `DistanceFrom(target, m)` | The distance between `argument` and `target` (computed by `std::abs(argument - target)`) matches `m`. |
45+
| `DistanceFrom(target, m)` | The distance between `argument` and `target` (computed by `abs(argument - target)`) matches `m`. |
4646
| `DistanceFrom(target, get_distance, m)` | The distance between `argument` and `target` (computed by `get_distance(argument, target)`) matches `m`. |
4747
| `IsTrue()` | `argument` evaluates to `true` in a Boolean context. |
4848
| `IsNull()` | `argument` is a `NULL` pointer (raw or smart). |

googlemock/include/gmock/gmock-matchers.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -3042,7 +3042,9 @@ auto Second(T& x, Rank1) -> decltype((x.second)) { // NOLINT
30423042
struct DefaultGetDistance {
30433043
template <typename T, typename U>
30443044
auto operator()(const T& lhs, const U& rhs) const {
3045-
return std::abs(lhs - rhs);
3045+
using std::abs;
3046+
// Allow finding abs() in the type's namespace via ADL.
3047+
return abs(lhs - rhs);
30463048
}
30473049
};
30483050

@@ -4470,7 +4472,7 @@ inline internal::FloatingEqMatcher<double> DoubleNear(double rhs,
44704472
//
44714473
// 1. compute the distance between the value and the target using
44724474
// get_distance(value, target) if get_distance is provided; otherwise compute
4473-
// the distance as std::abs(value - target).
4475+
// the distance as abs(value - target).
44744476
// 2. match the distance against the user-provided matcher m; if the match
44754477
// succeeds, the DistanceFrom() match succeeds.
44764478
//

googlemock/test/gmock-matchers-arithmetic_test.cc

+37
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,43 @@ TEST(DistanceFrom, CanCustomizeDistanceAndComparator) {
544544
EXPECT_FALSE(m.Matches(Double(0.61)));
545545
}
546546

547+
// For testing using DistanceFrom() with a type that supports both - and abs.
548+
class Float {
549+
public:
550+
explicit Float(float value) : value_(value) {}
551+
Float(const Float& other) = default;
552+
float value() const { return value_; }
553+
554+
private:
555+
float value_ = 0.0f;
556+
};
557+
558+
// Returns the difference between two Float values. This must be defined in the
559+
// same namespace as Float.
560+
Float operator-(const Float& lhs, const Float& rhs) {
561+
return Float(lhs.value() - rhs.value());
562+
}
563+
564+
// Returns the absolute value of a Float value. This must be defined in the
565+
// same namespace as Float.
566+
Float abs(Float value) { return Float(std::abs(value.value())); }
567+
568+
// Returns true if and only if the first Float value is less than the second
569+
// Float value. This must be defined in the same namespace as Float.
570+
bool operator<(const Float& lhs, const Float& rhs) {
571+
return lhs.value() < rhs.value();
572+
}
573+
574+
// Tests that DistanceFrom() can be used with a type that supports both - and
575+
// abs.
576+
TEST(DistanceFrom, CanBeUsedWithTypeThatSupportsBothMinusAndAbs) {
577+
const Matcher<Float> m = DistanceFrom(Float(0.5f), Lt(Float(0.1f)));
578+
EXPECT_TRUE(m.Matches(Float(0.45f)));
579+
EXPECT_TRUE(m.Matches(Float(0.55f)));
580+
EXPECT_FALSE(m.Matches(Float(0.39f)));
581+
EXPECT_FALSE(m.Matches(Float(0.61f)));
582+
}
583+
547584
// Tests that Not(m) matches any value that doesn't match m.
548585
TEST(NotTest, NegatesMatcher) {
549586
Matcher<int> m;

0 commit comments

Comments
 (0)