Объявление и определение объекта функции внутри функции-члена класса - PullRequest
0 голосов
/ 05 августа 2010

Интересно, можно ли и как определить объект функции внутри функции-члена класса, чтобы использовать его напрямую, например, с функцией std :: transform.
Я знаю, что этот пример немного глуп, онпросто чтобы показать проблему, с которой я столкнулся.

Файл "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])
}

Файл "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()

С тех пор, как я пытался реализовать объект функции непосредственно внутри функции-членакак в "example.cpp", код не компилируется.Я получаю сообщение об ошибке:

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>&)’

Так что я думаю, что проблема возникает при использовании структуры "functor" в std :: transform.Может кто-нибудь сказать мне, в чем проблема?

Использование:
компилятор gcc-4.2 под Ubuntu Linux.

Заранее спасибо,
René.

Ответы [ 2 ]

4 голосов
/ 05 августа 2010

Как уже говорил Александр, вы не можете использовать тип с областью действия функции (или вообще без имени) в качестве параметра шаблона. Однако вы можете использовать статическую функцию-член локального типа в качестве параметра функтора:

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);
}

Если вам нужно локальное состояние в вашей функции и вы не хотите прибегать к идиоме стирания типа, вы можете обмануть, отбросив локальный тип:

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));
}
2 голосов
/ 05 августа 2010

К сожалению, это не сработает. Стандарт запрещает использование локальных классов в качестве аргументов шаблона, поэтому подход не дает (пожалуйста, кто-нибудь, процитируйте соответствующую часть стандарта) :

14.3.1 / 2: "Локальный тип, тип без связи, безымянный тип или тип составлен из любого из этих типов не должен использоваться в качестве шаблон-аргумент для шаблона тип-параметр. "

Если у вас есть доступ к компилятору C ++ 0x, это работает.

Локальные классы могли бы быть мощными, но их использование несколько ограничено «идиомой стирания типа»:

struct abstract_foo { ... };

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

    return new foo(...);
}
...