4

Is there a some more standard way of applying an argument to range of functions? I came up with solutions like the one listed below, but it feels wrong - out there should be something already for building such logic.

template<typename Function, typename Result, typename Argument>
struct apply_argument_t {
    Argument x;
    Result operator () (Function f) {
        return f (x);
    }
};

Thus a simple use case:

transform (in.begin(), in.end(), out.begin(), apply_argument(x));

I intentionally skipped implementation details.

Edit: But anyway, as they were asked for:

in is a range of unary functions (e.g. vector<int(*)(char)>)

out is a range of these unary function's results (e.g. vector<int>)

apply_argument is like the structure but without the template specification and initialization (e.g. apply_argument_t<int(*)(char), int, char>)

Also I missed the remark that a solution for C++11 is not searched.

Rado
  • 766
  • 7
  • 14
  • I don't really understand the question. What is `in`, and `out`? What is `apply_argument` (an instance of the class template, but with what template arguments?)? – Nawaz Dec 02 '12 at 13:34

3 Answers3

1

I intentionally skipped implementation details.

Well those details include where you got e.g. the Argument type from.

Anyway, use a lambda.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • It's an element from range of unary functions, I also added some clarification - thanks for the remarks. I also commented that I don't search for C++11. – Rado Dec 08 '12 at 06:33
1

I agree with Alf, but let's show you how to do that in your case.

Here is a possible solution to your problem with lambdas in case you use C++11: (I use Function but you will need to use your own specific function type.)

Argument x;
transform (in.begin(), in.end(), out.begin(),
  [x](Function f)
  {
    return f(x);
  }
);

Further reading on wikipedia, C++11.

Barney Szabolcs
  • 11,846
  • 12
  • 66
  • 91
  • Thank you, I added some clarification also (no C++11 though), thus in your example it will be more like inversed: `e(f)`, `f` will be an object passed to function `e` found in range `in`. – Rado Dec 08 '12 at 06:40
  • `auto` is not valid in function parameters, so until we have polymorphic lambdas something like `decltype(in)::reference` can be used (`const_reference` is also an option or is even mandatory if `in` is `const`-qualified). – Luc Danton Dec 08 '12 at 08:03
  • @LucDanton: thx, I corrected it, sorry. You are right, he should supply his type at the lambda function. – Barney Szabolcs Dec 08 '12 at 08:32
0

If you don't intend to use C++11, there is a different solution using <functional> from STL:

#include <functional>
#include <algorithm>

template<typename Argument, typename Result>
Result apply_function(Return (*f)(Argument), Argument x)
{
  return f(x);
}

transform (in.begin(), in.end(), out.begin(), bind2nd(ptr_fun(apply_function), x) );

But I think your solution is cleaner. I could think about only one possible simplification:

template<typename Argument, typename Result>
struct apply_argument_t {
    Argument x;
    Result operator () (Result (*f)(Argument)) {
        return f (x);
    }
};

There should be a solution using Boost lambda library, but it does not work for some reason:

#include<boost/lambda/lambda.hpp>
#include<boost/lambda/bind.hpp>
using namespace boost::lambda;
transform(in.begin(), in.end(), out.begin(), bind(_1, x));

Reference also here. (I've tried everything, protect, too but they did not work.)

Barney Szabolcs
  • 11,846
  • 12
  • 66
  • 91
  • Placeholders don't easily work in the first position (that of the function), it's a much simpler design to simply not support that functionality, which is the case for all lazy evaluation libraries I know of. – Luc Danton Dec 08 '12 at 12:13
  • Yes, but then the documentation should tell this explicitly. There is even an example on Boost page where the placeholder is in the first position: `bind(_1, a, b, c)(foo);` – Barney Szabolcs Dec 08 '12 at 12:22