Question

I wonder if and how it is possible to define a function object inside a classes member function to use it directly with, for example, the std::transform function.
I know the example is a bit stupid, it's just to show the problem I'm confronted with.

File "example.h"

class Example {
  public:
  //.. constructor and destructor stuff
    std::string toString() const; //Converts 'mVal' to a std::string

  private:
    std::vector<int> mVal; //Only one digit numbers are allowed ([0-9])
}

File "example.cpp"

std::string Example::toString() const
{ 
  //The functor which should be used in std::transform
  struct {
    char operator()(const int number) {
      char c;
      //"Convert" 'number' to a char
      return c;
    };
  } functor;

  //Transform the integers to char
  std::string str(mVal.size(), '0'); //Allocate enough space
  std::transform(mVal.begin(), mVal.end(), str.begin(), functor);
  return str;

};//toString()

Ever since I tried to implement a function object directly inside a member function like in "example.cpp", the code doesn't get compiled. The error message I get is:

error: no matching function for call to ‘transform(__gnu_cxx::__normal_iterator<const int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<const int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Example::toString() const::<anonymous struct>&)’

So I think the problem comes up when using the struct "functor" in std::transform. Can someone tell me what the problem is?

Using:
gcc-4.2 compiler under Ubuntu Linux.

Thanks in advance,
René.

Was it helpful?

Solution

As Alexandre already pointed out, you can't use an type with function scope (or no name at all) as a template parameter. You can however use a static member function of a local type as a functor parameter:

int main()
{
    struct F {
        static int fn(int x)
        {
            return x+x;
        }
    }; 

    int v[5]={1,2,3,4,5};
    std::transform(v+0,v+5,v+0,F::fn);
}

If you need to a local state in your function and don't want to resort to the type erasure idiom, then you can cheat with casting the local type away:

int main()
{
    struct F {
        int k;
        int call (int n) const 
        {

            return n+k;
        }
        static int fn(void *p, int x)
        {
            return ((F*)p)->call(x); 
        }
    }; 

    int v[5]={1,2,3,4,5};
    F f;
    f.k=123;
    std::transform(v+0,v+5,v+0,std::bind1st(std::ptr_fun(F::fn),(void*)&f));
}

OTHER TIPS

Sadly, this won't work. Standard disallows local classes to be used as template arguments, so the approach fails (please someone, quote the relevant part of the Standard):

14.3.1/2: "A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter."

If you have access to a C++0x compiler this works though.

Local classes could have been powerful, but their use is somewhat limited to the "type erasure idiom":

struct abstract_foo { ... };

template <typename T>
abstract_foo* make_concrete_foo(...)
{
    struct foo : abstract_foo
    {
        // Depends on T
    };

    return new foo(...);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top