Commit dd8bc240 authored by Dominik Charousset's avatar Dominik Charousset

added new match_for function and slightly changed match_each

parent 5baa0736
...@@ -66,70 +66,86 @@ struct match_helper { ...@@ -66,70 +66,86 @@ struct match_helper {
} }
}; };
template<typename Iterator> struct identity_fun {
struct match_each_helper { template<typename T>
inline auto operator()(T&& arg) -> decltype(std::forward<T>(arg)) {
return std::forward<T>(arg);
}
};
template<typename Iterator, typename Projection = identity_fun>
class match_each_helper {
public:
match_each_helper(match_each_helper&&) = default;
match_each_helper(const match_each_helper&) = delete; match_each_helper(const match_each_helper&) = delete;
match_each_helper& operator=(const match_each_helper&) = delete; match_each_helper& operator=(const match_each_helper&) = delete;
Iterator i;
Iterator e;
match_each_helper(Iterator first, Iterator last) : i(first), e(last) { } match_each_helper(Iterator first, Iterator last) : i(first), e(last) { }
match_each_helper(match_each_helper&&) = default; match_each_helper(Iterator first, Iterator last, Projection proj)
void operator()(partial_function&& arg) { : i(first), e(last), p(proj) { }
partial_function tmp{std::move(arg)};
template<typename... Cases>
void operator()(match_expr<Cases...> expr) {
for (; i != e; ++i) { for (; i != e; ++i) {
tmp(any_tuple::view(*i)); expr(p(*i));
} }
} }
template<class Arg0, class... Args>
void operator()(Arg0&& arg0, Args&&... args) {
(*this)(match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...));
}
};
template<class Container> template<class Arg0, class Arg1, class... Args>
struct copying_match_each_helper { void operator()(Arg0&& arg0, Arg1&& arg1, Args&&... args) {
copying_match_each_helper(const copying_match_each_helper&) = delete; (*this)(match_expr_collect(std::forward<Arg0>(arg0),
copying_match_each_helper& operator=(const copying_match_each_helper&) = delete; std::forward<Arg1>(arg1),
Container vec;
copying_match_each_helper(Container tmp) : vec(std::move(tmp)) { }
copying_match_each_helper(copying_match_each_helper&&) = default;
void operator()(partial_function&& arg) {
partial_function tmp{std::move(arg)};
for (auto& i : vec) {
tmp(any_tuple::view(i));
}
}
template<class Arg0, class... Args>
void operator()(Arg0&& arg0, Args&&... args) {
(*this)(match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...)); std::forward<Args>(args)...));
} }
};
template<typename Iterator, typename Projection> private:
struct pmatch_each_helper {
pmatch_each_helper(const pmatch_each_helper&) = delete;
pmatch_each_helper& operator=(const pmatch_each_helper&) = delete;
Iterator i; Iterator i;
Iterator e; Iterator e;
Projection p; Projection p;
pmatch_each_helper(pmatch_each_helper&&) = default;
template<typename PJ> };
pmatch_each_helper(Iterator first, Iterator last, PJ&& proj)
: i(first), e(last), p(std::forward<PJ>(proj)) { struct advance_once {
} template<typename T>
void operator()(partial_function&& arg) { inline void operator()(T& what) { ++what; }
partial_function tmp{std::move(arg)}; };
for (; i != e; ++i) {
tmp(any_tuple::view(p(*i))); template<class Iterator, class Predicate,
class Advance = advance_once,
class Projection = identity_fun>
class match_for_helper {
public:
match_for_helper(match_for_helper&&) = default;
match_for_helper(const match_for_helper&) = delete;
match_for_helper& operator=(const match_for_helper&) = delete;
match_for_helper(Iterator first, Predicate p, Advance a = Advance(), Projection pj = Projection())
: i(first), adv(a), pred(p), proj(pj) { }
template<typename... Cases>
void operator()(match_expr<Cases...> expr) {
for (; pred(i); adv(i)) {
expr(proj(*i));
} }
} }
template<class Arg0, class... Args>
void operator()(Arg0&& arg0, Args&&... args) { template<class Arg0, class Arg1, class... Args>
(*this)(match_expr_convert(std::forward<Arg0>(arg0), void operator()(Arg0&& arg0, Arg1&& arg1, Args&&... args) {
(*this)(match_expr_collect(std::forward<Arg0>(arg0),
std::forward<Arg1>(arg1),
std::forward<Args>(args)...)); std::forward<Args>(args)...));
} }
private:
Iterator i;
Advance adv;
Predicate pred;
Projection proj;
}; };
// Case is a projection_partial_function_pair // Case is a projection_partial_function_pair
...@@ -312,31 +328,6 @@ detail::match_helper match(T&& what) { ...@@ -312,31 +328,6 @@ detail::match_helper match(T&& what) {
return any_tuple::view(std::forward<T>(what)); return any_tuple::view(std::forward<T>(what));
} }
/**
* @brief Starts a match expression that matches each element of @p what.
* @param what An STL-compliant container.
* @returns A helper object providing <tt>operator(...)</tt>.
*/
template<class Container>
auto match_each(Container& what)
-> detail::match_each_helper<decltype(std::begin(what))> {
return {std::begin(what), std::end(what)};
}
/**
* @brief Starts a match expression that matches each element of @p what.
* @param what An STL-compliant container.
* @returns A helper object providing <tt>operator(...)</tt>.
*/
template<typename T>
auto match_each(std::initializer_list<T> what)
-> detail::copying_match_each_helper<std::vector<typename detail::strip_and_convert<T>::type>> {
std::vector<typename detail::strip_and_convert<T>::type> vec;
vec.reserve(what.size());
for (auto& i : what) vec.emplace_back(std::move(i));
return vec;
}
/** /**
* @brief Starts a match expression that matches each element in * @brief Starts a match expression that matches each element in
* range [first, last). * range [first, last).
...@@ -360,10 +351,28 @@ auto match_each(InputIterator first, InputIterator last) ...@@ -360,10 +351,28 @@ auto match_each(InputIterator first, InputIterator last)
*/ */
template<typename InputIterator, typename Projection> template<typename InputIterator, typename Projection>
auto match_each(InputIterator first, InputIterator last, Projection proj) auto match_each(InputIterator first, InputIterator last, Projection proj)
-> detail::pmatch_each_helper<InputIterator, Projection> { -> detail::match_each_helper<InputIterator, Projection> {
return {first, last, std::move(proj)}; return {first, last, std::move(proj)};
} }
template<typename InputIterator, typename Predicate>
auto match_for(InputIterator first, Predicate pred)
-> detail::match_for_helper<InputIterator, Predicate> {
return {first, std::move(pred)};
}
template<typename InputIterator, typename Predicate, typename Advance>
auto match_for(InputIterator first, Predicate pred, Advance adv)
-> detail::match_for_helper<InputIterator, Predicate, Advance> {
return {first, std::move(pred), std::move(adv)};
}
template<class InputIterator, class Predicate, class Advance, class Projection>
auto match_for(InputIterator first, Predicate pred, Advance adv, Projection pj)
-> detail::match_for_helper<InputIterator, Predicate, Advance, Projection>{
return {first, std::move(pred), std::move(adv), std::move(pj)};
}
template<typename T> template<typename T>
detail::stream_matcher<T, std::istream_iterator<T> > match_stream(std::istream& stream) { detail::stream_matcher<T, std::istream_iterator<T> > match_stream(std::istream& stream) {
std::istream_iterator<T> first(stream); std::istream_iterator<T> first(stream);
......
...@@ -236,7 +236,8 @@ int main() { ...@@ -236,7 +236,8 @@ int main() {
invoked = false; invoked = false;
string sum; string sum;
match_each({"-h", "--version", "-wtf"}) ( vector<string> sum_args = { "-h", "--version", "-wtf" };
match_each(begin(sum_args), end(sum_args)) (
on<string>().when(_x1.in({"-h", "--help"})) >> [&](string s) { on<string>().when(_x1.in({"-h", "--help"})) >> [&](string s) {
sum += s; sum += s;
}, },
...@@ -248,6 +249,9 @@ int main() { ...@@ -248,6 +249,9 @@ int main() {
on<char>().when(_x1.in({'w', 't', 'f'})) >> [&](char c) { on<char>().when(_x1.in({'w', 't', 'f'})) >> [&](char c) {
sum += c; sum += c;
}, },
on<char>() >> [&](char c) {
CPPA_ERROR("whaaaaat? guard didn't match: " << c);
},
others() >> [&]() { others() >> [&]() {
CPPA_ERROR("unexpected match"); CPPA_ERROR("unexpected match");
} }
...@@ -279,7 +283,7 @@ int main() { ...@@ -279,7 +283,7 @@ int main() {
CPPA_CHECK_EQUAL("C", vec.back()); CPPA_CHECK_EQUAL("C", vec.back());
invoked = false; invoked = false;
match_each(vec) ( match_each(begin(vec), end(vec)) (
on("a") >> [&](string& str) { on("a") >> [&](string& str) {
invoked = true; invoked = true;
str = "A"; str = "A";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment