Timeline for A recursive_count_if Function For Various Type Arbitrary Nested Iterable Implementation in C++
Current License: CC BY-SA 4.0
11 events
| when toggle format | what | by | license | comment | |
|---|---|---|---|---|---|
| Nov 17, 2020 at 3:50 | comment | added | JimmyHu | @Quuxplusone I am trying to implement another version of recursive_count_if with specified value_type based on G. Sliepen's comments, please check codereview.stackexchange.com/q/252225/231235 | |
| Nov 16, 2020 at 17:45 | comment | added | Quuxplusone | Vice versa, if p were, like, [](auto x) { return x.size()==5; }, then the question arises whether we might want to apply it at multiple levels! Is this like that "How many squares do you see?" brainteaser? :) Really, I just think it's a bad API. Using a library API as simple as count_if shouldn't require the user to solve a puzzle. | |
| Nov 16, 2020 at 17:40 | comment | added | Quuxplusone | @G.Sliepen: Right, "check whether applying p to a T1 is well-formed" is easy and unambiguous; but then it requires the user to define their predicate p so that it is SFINAE-friendly, which generic lambdas aren't, in general. E.g. try your idea with recursive_count_if(vec_of_vec_of_string, [](const auto& s) { return s.starts_with("foo"); }). It blows up because p(vec_of_vec_of_string[0]) seems well-formed yet when we go to instantiate p's body we find that vector<string> has no member function starts_with (and by then it's too late to backtrack). | |
| Nov 16, 2020 at 17:03 | comment | added | G. Sliepen | @Quuxplusone: That's a very informative blog post. Although I'm not suggesting to determine the type of parameter T2 takes, but just to check whether applying T2 to a T1 works. That should be more well-defined, but of course might be surprising if you use a generic lambda and it matches the value_type of the outer container when you expect it to go down to the inner-most container. | |
| Nov 16, 2020 at 15:07 | comment | added | Quuxplusone | @G.Sliepen: Think about when p is a generic lambda. In general, "figuring out the argument type of a callable" is a fool's errand. See quuxplusone.github.io/blog/2018/06/12/perennial-impossibilities/… | |
| Nov 16, 2020 at 14:55 | comment | added | Quuxplusone | @JimmyHu: You're trying to specialize foo<0, T1, T2> differently from foo<N, T1, T2>, right? Think about how you could use if constexpr here; or, pre-C++17, think about what you could do with overload resolution if foo<I, T1, T2> consists of the single statement return fooImpl<T1, T2>(std::index_constant<I>(), r, p);. </hint> | |
| Nov 16, 2020 at 7:31 | comment | added | JimmyHu | @Quuxplusone I am trying to implement the function which could be used like recursive_count_if<N>(r, p). However, the function template can't be designed with the syntax similar to template<std::size_t N, class T1, class T2> because function template partial specialization is not allowed. If there is any hint to deal with this problem, please let me know. | |
| Nov 16, 2020 at 1:16 | comment | added | JimmyHu | @G.Sliepen I also think so. The point is to make recursion stops properly in the right time based on the type matching process. | |
| Nov 16, 2020 at 0:13 | vote | accept | JimmyHu | ||
| Nov 15, 2020 at 23:18 | comment | added | G. Sliepen | Good point about std::string. But maybe it can be made to work if recursion stops automatically if, for recursive_count(), the container's value_type matches T2 (or rather, that T2{}==(*T1{}.begin()) is a valid expression), and in the case of recursive_count_if, if T2::operator()(*T1{}.begin()) is a valid expression? | |
| Nov 15, 2020 at 20:00 | history | answered | Quuxplusone | CC BY-SA 4.0 |