Такой IteratorRange
будет работать в большинстве случаев - для ограничения смотреть в Сличитель тела:
MATCHER_P(IteratorRange, param, "")
{
auto begin = get<0>(arg);
auto end = get<1>(arg);
// these two lines might be weak point of this matcher implementation...
// I mean:
// 1. constructing vector might be not supported
// e.g. object are not copyable)
// 2. copying objects from range might "change" the tested code behavior
// e.g. copy is badly implemented
// 3. it is for sure "performance" degradation
using value_type = typename std::iterator_traits<decltype(begin)>::value_type;
std::vector<value_type> range{begin, end};
Matcher<decltype(range)> matcher = param;
return matcher.MatchAndExplain(range, result_listener);
}
Он может быть использован, как это:
TEST(A,A)
{
int a,b,c;
std::vector<int> values{ a,b,c };
MyMock m;
EXPECT_CALL(m, f(_,_,_,_)).With(Args<1,2>(IteratorRange(ContainerEq(values))));
m.f(X{}, values.begin(), values.end(), Y{});
}
[UPDATE]
Преодолеть недостатки этой цели rnal копирование диапазона в контейнер - вам нужно придумать легкий контейнер - как этот:
template <typename Iterator>
class RangeView
{
public:
using iterator = Iterator;
using const_iterator = Iterator;
using value_type = typename std::iterator_traits<Iterator>::value_type;
RangeView(Iterator begin, Iterator end) : beginIter(begin), endIter(end) {}
iterator begin() const { return beginIter; }
iterator end() const { return endIter; }
std::size_t size() const { return std::distance(beginIter, endIter); }
bool operator == (const RangeView& other) const
{
return size() == other.size() && std::equal(beginIter, endIter, other.beginIter);
}
private:
Iterator beginIter, endIter;
};
Plus некоторые вспомогательные функции, чтобы сделать его проще использовать этот класс:
template <typename Iterator>
void PrintTo(RangeView<Iterator> const& range, std::ostream* os)
{
*os << "{";
for (auto&& e: range) *os << "[" << PrintToString(e) << "]";
*os << "}";
}
template <typename Iterator>
RangeView<Iterator> makeRangeView(Iterator begin, Iterator end)
{
return RangeView<Iterator>(begin, end);
}
template <typename Container>
auto makeRangeView(Container const& container)
{
return makeRangeView(std::begin(container), std::end(container));
}
Обратите внимание, что если вы используйте boost в своем проекте - вы можете использовать range from boost - вам не нужно «изобретать колесо».
Затем - свет согласовань может быть определена без этих недостатков:
MATCHER_P(IteratorRangeLight, param, "")
{
auto begin = get<0>(arg);
auto end = get<1>(arg);
auto range = makeRangeView(begin, end);
Matcher<decltype(range)> matcher = param;
return matcher.MatchAndExplain(range, result_listener);
}
Тогда - использовать его как это:
TEST(A,A)
{
int a=1,b=2,c=3;
std::vector<int> values{ a,b,c };
MyMock m;
EXPECT_CALL(m, f(_,_,_,_)).
With(Args<1,2>(IteratorRangeLight(ContainerEq(makeRangeView(values)))));
// ^^^^^^^^^^^^^
// note that you need to use makeRangeView also within the matcher
m.f(X{}, values.begin(), values.end(), Y{});
}
Есть ли способ сделать Googlemock matchers применимо к 'повышению :: range'? Это может обеспечить необходимый мост ... – SimonD