257
257
258
258
#include < algorithm>
259
259
#include < cmath>
260
+ #include < cstddef>
260
261
#include < exception>
261
262
#include < functional>
262
263
#include < initializer_list>
@@ -2097,11 +2098,11 @@ class WhenDynamicCastToMatcher<To&> : public WhenDynamicCastToMatcherBase<To&> {
2097
2098
template <typename Class, typename FieldType>
2098
2099
class FieldMatcher {
2099
2100
public:
2100
- FieldMatcher (FieldType Class::*field,
2101
+ FieldMatcher (FieldType Class::* field,
2101
2102
const Matcher<const FieldType&>& matcher)
2102
2103
: field_(field), matcher_(matcher), whose_field_(" whose given field " ) {}
2103
2104
2104
- FieldMatcher (const std::string& field_name, FieldType Class::*field,
2105
+ FieldMatcher (const std::string& field_name, FieldType Class::* field,
2105
2106
const Matcher<const FieldType&>& matcher)
2106
2107
: field_(field),
2107
2108
matcher_ (matcher),
@@ -2145,7 +2146,7 @@ class FieldMatcher {
2145
2146
return MatchAndExplainImpl (std::false_type (), *p, listener);
2146
2147
}
2147
2148
2148
- const FieldType Class::*field_;
2149
+ const FieldType Class::* field_;
2149
2150
const Matcher<const FieldType&> matcher_;
2150
2151
2151
2152
// Contains either "whose given field " if the name of the field is unknown
@@ -3291,8 +3292,8 @@ class PairMatcher {
3291
3292
};
3292
3293
3293
3294
template <typename T, size_t ... I>
3294
- auto UnpackStructImpl (const T& t, std::index_sequence<I...>,
3295
- int ) -> decltype(std::tie(get<I>(t)...)) {
3295
+ auto UnpackStructImpl (const T& t, std::index_sequence<I...>, int )
3296
+ -> decltype(std::tie(get<I>(t)...)) {
3296
3297
static_assert (std::tuple_size<T>::value == sizeof ...(I),
3297
3298
" Number of arguments doesn't match the number of fields." );
3298
3299
return std::tie (get<I>(t)...);
@@ -3581,7 +3582,7 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
3581
3582
StlContainerReference stl_container = View::ConstReference (container);
3582
3583
auto it = stl_container.begin ();
3583
3584
size_t exam_pos = 0 ;
3584
- bool mismatch_found = false ; // Have we found a mismatched element yet?
3585
+ bool unmatched_found = false ;
3585
3586
3586
3587
// Go through the elements and matchers in pairs, until we reach
3587
3588
// the end of either the elements or the matchers, or until we find a
@@ -3597,11 +3598,23 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
3597
3598
}
3598
3599
3599
3600
if (!match) {
3600
- mismatch_found = true ;
3601
+ unmatched_found = true ;
3602
+ // We cannot store the iterator for the unmatched element to be used
3603
+ // later, as some users use ElementsAre() with a "container" whose
3604
+ // iterator is not copy-constructible or copy-assignable.
3605
+ //
3606
+ // We cannot store a pointer to the element either, as some container's
3607
+ // iterators return a temporary.
3608
+ //
3609
+ // We cannot store the element itself either, as the element may not be
3610
+ // copyable.
3611
+ //
3612
+ // Therefore, we just remember the index of the unmatched element,
3613
+ // and use it later to print the unmatched element.
3601
3614
break ;
3602
3615
}
3603
3616
}
3604
- // If mismatch_found is true, ' exam_pos' is the index of the mismatch.
3617
+ // If unmatched_found is true, exam_pos is the index of the mismatch.
3605
3618
3606
3619
// Find how many elements the actual container has. We avoid
3607
3620
// calling size() s.t. this code works for stream-like "containers"
@@ -3622,10 +3635,27 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
3622
3635
return false ;
3623
3636
}
3624
3637
3625
- if (mismatch_found ) {
3638
+ if (unmatched_found ) {
3626
3639
// The element count matches, but the exam_pos-th element doesn't match.
3627
3640
if (listener_interested) {
3628
- *listener << " whose element #" << exam_pos << " doesn't match" ;
3641
+ // Find the unmatched element.
3642
+ auto unmatched_it = stl_container.begin ();
3643
+ // We cannot call std::advance() on the iterator, as some users use
3644
+ // ElementsAre() with a "container" whose iterator is incompatible with
3645
+ // std::advance() (e.g. it may not have the difference_type member
3646
+ // type).
3647
+ for (size_t i = 0 ; i != exam_pos; ++i) {
3648
+ ++unmatched_it;
3649
+ }
3650
+
3651
+ // If the array is long or the elements' print-out is large, it may be
3652
+ // hard for the user to find the mismatched element and its
3653
+ // corresponding matcher description. Therefore we print the index, the
3654
+ // value of the mismatched element, and the corresponding matcher
3655
+ // description to ease debugging.
3656
+ *listener << " whose element #" << exam_pos << " ("
3657
+ << PrintToString (*unmatched_it) << " ) " ;
3658
+ matchers_[exam_pos].DescribeNegationTo (listener->stream ());
3629
3659
PrintIfNotEmpty (explanations[exam_pos], listener->stream ());
3630
3660
}
3631
3661
return false ;
@@ -4031,15 +4061,15 @@ GTEST_API_ std::string FormatMatcherDescription(
4031
4061
// Overloads to support `OptionalMatcher` being used with a type that either
4032
4062
// supports implicit conversion to bool or a `has_value()` method.
4033
4063
template <typename Optional>
4034
- auto IsOptionalEngaged (const Optional& optional,
4035
- Rank1) -> decltype(!!optional) {
4064
+ auto IsOptionalEngaged (const Optional& optional, Rank1)
4065
+ -> decltype(!!optional) {
4036
4066
// The use of double-negation here is to preserve historical behavior where
4037
4067
// the matcher used `operator!` rather than directly using `operator bool`.
4038
4068
return !static_cast <bool >(!optional);
4039
4069
}
4040
4070
template <typename Optional>
4041
- auto IsOptionalEngaged (const Optional& optional,
4042
- Rank0) -> decltype(!optional.has_value()) {
4071
+ auto IsOptionalEngaged (const Optional& optional, Rank0)
4072
+ -> decltype(!optional.has_value()) {
4043
4073
return optional.has_value ();
4044
4074
}
4045
4075
@@ -4567,7 +4597,7 @@ WhenDynamicCastTo(const Matcher<To>& inner_matcher) {
4567
4597
// matches a Foo object x if and only if x.number >= 5.
4568
4598
template <typename Class, typename FieldType, typename FieldMatcher>
4569
4599
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field (
4570
- FieldType Class::*field, const FieldMatcher& matcher) {
4600
+ FieldType Class::* field, const FieldMatcher& matcher) {
4571
4601
return MakePolymorphicMatcher (internal::FieldMatcher<Class, FieldType>(
4572
4602
field, MatcherCast<const FieldType&>(matcher)));
4573
4603
// The call to MatcherCast() is required for supporting inner
@@ -4580,7 +4610,7 @@ inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
4580
4610
// messages.
4581
4611
template <typename Class, typename FieldType, typename FieldMatcher>
4582
4612
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field (
4583
- const std::string& field_name, FieldType Class::*field,
4613
+ const std::string& field_name, FieldType Class::* field,
4584
4614
const FieldMatcher& matcher) {
4585
4615
return MakePolymorphicMatcher (internal::FieldMatcher<Class, FieldType>(
4586
4616
field_name, field, MatcherCast<const FieldType&>(matcher)));
0 commit comments