3

Based on std::transform

template < class InputIterator, class OutputIterator, class UnaryOperator >
  OutputIterator transform ( InputIterator first1, InputIterator last1,
                             OutputIterator result, UnaryOperator op );

Can op be a member function? If so, how do I call it?

wilhelmtell
  • 57,473
  • 20
  • 96
  • 131
q0987
  • 34,938
  • 69
  • 242
  • 387
  • See [Boost.Bind](http://www.boost.org/libs/bind/). – ildjarn Jan 26 '12 at 19:58
  • http://stackoverflow.com/questions/1762781/mem-fun-and-bind1st-problem – q0987 Jan 26 '12 at 20:06
  • You question is slightly ambiguous. What class are you hoping to make `op` a member of? The class of `*first1`, the class of `*result`, the class of `*this`, or some other class? – Robᵩ Jan 26 '12 at 20:22
  • @Rob, it is best if I know both cases. – q0987 Jan 26 '12 at 20:32
  • @q0987 - see my answer. It describes the case of `op` being a member of the class of `*first1` and the case of `op` being a member of `*this`. You should be able to generalize from there. – Robᵩ Jan 26 '12 at 20:33

3 Answers3

4

No (well, not directly). You need to use an adaptor, either old std::mem_fun (together with bind1st, IIRC) or std::bind/boost::bind.

std::transform(
    xs.begin(), xs.end(), ys.begin(),
    std::bind(&Class::member, &class_instance)
);
Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
3

It is pretty easy to do if you wrap the call in lambda:

#include <algorithm>
#include <vector>

class C {
public:
  int op() const { return 1; }
};

class D {
  int op() { return 1; }
  void f() {
    std::vector<C> xs;
    std::vector<int> ys;
    std::transform(xs.begin(), xs.end(), ys.begin(),
      [](const C& x) { return x.op(); });
    std::transform(xs.begin(), xs.end(), ys.begin(),
      [this](const C& x) { return this->op(); });
  }
};
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
2

You need a helper object, like std::less but for a unary operator.

C++11 lambdas make this incredibly easy:

std::transform(xs.begin(), xs.end(), ys.begin(), [](the_type x){ return -x; });
std::transform(xs.begin(), xs.end(), ys.begin(), [](the_type x){ return !x; });
std::transform(xs.begin(), xs.end(), ys.begin(), [](the_type x){ return ~x; });

Or, use these flexible helpers:

struct negate
{
    template<typename T>
    auto operator()(const T& x) const -> decltype(-x) { return -x; }
};

struct invert
{
    template<typename T>
    auto operator()(const T& x) const -> decltype(!x) { return !x; }
};

struct complement
{
    template<typename T>
    auto operator()(const T& x) const -> decltype(~x) { return ~x; }
};

std::transform(xs.begin(), xs.end(), ys.begin(), negate());
std::transform(xs.begin(), xs.end(), ys.begin(), invert());
std::transform(xs.begin(), xs.end(), ys.begin(), complement());
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720