Un tel IteratorRange
fonctionnera dans la plupart des cas - pour limiter l'air dans le corps matcher:
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);
}
Il peut être utilisé comme ceci:
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]
Le surmonter les inconvénients de cette inte rn copie d'une plage dans le récipient - vous avez besoin d'inventer le récipient de lumière - comme celui-ci:
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 une fonction d'aide pour le rendre plus facile à utiliser cette classe:
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));
}
Notez que si vous utilisez boost dans votre projet - vous pouvez utiliser range from boost - vous n'avez pas besoin de "réinventer la roue".
Puis - matcher la lumière peut être définie sans ces inconvénients:
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);
}
Puis - l'utiliser comme ceci:
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{});
}
est-il un moyen de faire le Googlemock Matchers applicable à 'boost :: gamme'? Cela pourrait fournir le pont nécessaire ... – SimonD