0

I need a function apply(Function f, Container &c) which would apply a given function to a range (container).

std::vector<int> a = {1, 5, 2, 4, 3};
apply(std::sort, a); // {1, 2, 3, 4, 5}
apply(std::reverse, a); // {5, 4, 3, 2, 1}

This is a basic example of the behaviour I am looking for. Also, returning the value of the function (for example std::max_element) and variadic arguments (lambda comparators for sorting) would be nice bonuses.

Actually I can't even pass std::sort or std::reverse as a function to a function. What I tried is:

template<typename F, typename T>
void apply(const F &f, T &a) {
    f(a.begin(), a.end());
}

and:

template<typename T, typename U>
U apply(U (*f)(typename T::iterator, typename T::iterator), T &a) {
    return (*f)(a.begin(), a.end());
}

Both are giving me apply(<unresolved overloaded function type>, std::vector<int>&).

So, is there a way to do it and what's the most modern way to do it?

  • * There's https://stackoverflow.com/questions/4697180/template-function-as-a-template-argument but I think it only works if you know exactly the type. – user202729 Oct 02 '21 at 02:04
  • 2
    • You can make a lambda function to wrap the sort function instead. Does that satisfy your requirement or "too verbose"? – user202729 Oct 02 '21 at 02:04
  • Or equivalently a function object class [c++ - How to pass an overloaded function pointer as an argument without resolving (C++03) - Stack Overflow](https://stackoverflow.com/questions/35759460/how-to-pass-an-overloaded-function-pointer-as-an-argument-without-resolving-c). – user202729 Oct 02 '21 at 02:06
  • 4
    The problem is that `std::sort` isn't a function, it's a collection of multiple function templates. One approach is to specify a specific instantiation [like so](https://godbolt.org/z/dxzf75a81). – Nathan Pierson Oct 02 '21 at 02:06
  • 1
    @NathanPierson Is that really okay? https://stackoverflow.com/a/68555771/5267751 – user202729 Oct 02 '21 at 02:07
  • Very peculiar! Good catch – Nathan Pierson Oct 02 '21 at 02:10
  • Why? this seems redundant and dispensable. Ah, you want to type less on your keyboard! – Captain Giraffe Oct 02 '21 at 02:11
  • 2
    @NathanPierson You can't even pick a specialization, because the standard [forbids the creation of a "pointer to function" for any standard library function or instantiation of a templated standard library function](https://timsong-cpp.github.io/cppwp/requirements#namespace.std-6), except for so-called "addressable functions". This restriction necessary because many functions internally use `std::enable_if` or default parameters to control whether they participate in overload resolution. – Raymond Chen Oct 02 '21 at 02:29
  • 1
    I've closed the question as a duplicate. Based on this comment thread, it's not clear to me whether any of the answers on the target are correct, so you might want to look at the linked resources in these comments as well. – cigien Oct 02 '21 at 02:34
  • FWIW, there are range versions of algorithms now if that's where you were headed: `std::ranges::sort(a);`. You can, of course, use a namespace alias. – chris Oct 02 '21 at 03:20

0 Answers0