0

我想知道是否以及如何在类成员函数中定义一个函数对象以直接使用它,例如 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>&)’

所以我认为在std::transform中使用struct“functor”时会出现问题。有人可以告诉我问题是什么吗?

使用:
Ubuntu Linux下的gcc-4.2编译器。

在此先感谢,
勒内。

4

2 回答 2

4

正如 Alexandre 已经指出的那样,您不能将具有函数范围(或根本没有名称)的类型用作模板参数。但是,您可以使用本地类型的静态成员函数作为仿函数参数:

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));
}
于 2010-08-05T09:29:36.557 回答
2

可悲的是,这行不通。标准不允许将本地类用作模板参数,因此该方法失败(请某人引用标准的相关部分)

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(...);
}
于 2010-08-05T08:59:03.703 回答