0
0
mirror of https://github.com/google/googletest.git synced 2025-03-20 10:53:47 +00:00

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
This commit is contained in:
Zhanyong Wan 2025-03-11 06:58:07 -07:00 committed by Copybara-Service
parent 0bdccf4aa2
commit 4ee4b17bf5
3 changed files with 42 additions and 3 deletions

View File

@ -42,7 +42,7 @@ Matcher | Description
| `Lt(value)` | `argument < value` |
| `Ne(value)` | `argument != value` |
| `IsFalse()` | `argument` evaluates to `false` in a Boolean context. |
| `DistanceFrom(target, m)` | The distance between `argument` and `target` (computed by `std::abs(argument - target)`) matches `m`. |
| `DistanceFrom(target, m)` | The distance between `argument` and `target` (computed by `abs(argument - target)`) matches `m`. |
| `DistanceFrom(target, get_distance, m)` | The distance between `argument` and `target` (computed by `get_distance(argument, target)`) matches `m`. |
| `IsTrue()` | `argument` evaluates to `true` in a Boolean context. |
| `IsNull()` | `argument` is a `NULL` pointer (raw or smart). |

View File

@ -3042,7 +3042,9 @@ auto Second(T& x, Rank1) -> decltype((x.second)) { // NOLINT
struct DefaultGetDistance {
template <typename T, typename U>
auto operator()(const T& lhs, const U& rhs) const {
return std::abs(lhs - rhs);
using std::abs;
// Allow finding abs() in the type's namespace via ADL.
return abs(lhs - rhs);
}
};
@ -4470,7 +4472,7 @@ inline internal::FloatingEqMatcher<double> DoubleNear(double rhs,
//
// 1. compute the distance between the value and the target using
// get_distance(value, target) if get_distance is provided; otherwise compute
// the distance as std::abs(value - target).
// the distance as abs(value - target).
// 2. match the distance against the user-provided matcher m; if the match
// succeeds, the DistanceFrom() match succeeds.
//

View File

@ -544,6 +544,43 @@ TEST(DistanceFrom, CanCustomizeDistanceAndComparator) {
EXPECT_FALSE(m.Matches(Double(0.61)));
}
// For testing using DistanceFrom() with a type that supports both - and abs.
class Float {
public:
explicit Float(float value) : value_(value) {}
Float(const Float& other) = default;
float value() const { return value_; }
private:
float value_ = 0.0f;
};
// Returns the difference between two Float values. This must be defined in the
// same namespace as Float.
Float operator-(const Float& lhs, const Float& rhs) {
return Float(lhs.value() - rhs.value());
}
// Returns the absolute value of a Float value. This must be defined in the
// same namespace as Float.
Float abs(Float value) { return Float(std::abs(value.value())); }
// Returns true if and only if the first Float value is less than the second
// Float value. This must be defined in the same namespace as Float.
bool operator<(const Float& lhs, const Float& rhs) {
return lhs.value() < rhs.value();
}
// Tests that DistanceFrom() can be used with a type that supports both - and
// abs.
TEST(DistanceFrom, CanBeUsedWithTypeThatSupportsBothMinusAndAbs) {
const Matcher<Float> m = DistanceFrom(Float(0.5f), Lt(Float(0.1f)));
EXPECT_TRUE(m.Matches(Float(0.45f)));
EXPECT_TRUE(m.Matches(Float(0.55f)));
EXPECT_FALSE(m.Matches(Float(0.39f)));
EXPECT_FALSE(m.Matches(Float(0.61f)));
}
// Tests that Not(m) matches any value that doesn't match m.
TEST(NotTest, NegatesMatcher) {
Matcher<int> m;