在 c++98 中创建泛型函子

Create a generic functor in c++98

本文关键字:泛型 创建 c++98      更新时间:2023-10-16

作为一个学校项目,我必须在 c++98 中创建一个泛型函子。

它必须像这样可用:

Function<int (char)> f1 = &functionPointer;
f1(’c’);
Function<int (char)> f2 = std::bind(&object, std::placeholders::_1);
f2(’c’);
Function<int (char)> f3 = &object;
f3(’c’);

为此,我定义了一个模板化类来接受可调用对象。在此类中,我定义了一个接口来抽象存储的函子的类型。运算符 = 重载 在 Function 类调用运算符 = 存储的内部函子的重载。

这适用于函数指针f1,但不适用于可调用对象f3或传递std::bind的结果...

int funct1(const std::string &str)
{
    std::cout << str << std::endl;
    return 0;
}
Function<int(const std::string &)> b = std::bind(&funct1, std::placeholders::_1);

这给了我这个错误(我在代码上评论了负责的行(:

invalid cast from type ‘const std::__cxx11::basic_string<char>’ to type ‘int’

我在这里做错了什么? :)

我的代码 :

template <typename T>
class Function;
template <typename T, typename P>
class Function<T(P)>
{
  typedef T (*fp)(P);
  // Interface representing the generic callable object
  class IFunctorType
  {
  public:
    virtual T operator()(P const &) = 0;
    virtual ~IFunctorType(){};
  };
  // templated class to represent callable object
  template <typename C>
  class FunctorType : public IFunctorType
  {
  public:
    FunctorType() : ftor_ptr_(0) {}
    FunctorType(C const &p) : ftor_ptr_(new C(p)) {}
    FunctorType(FunctorType<C> const &f) : ftor_ptr_(f.ftor_ptr_) {}
    FunctorType(FunctorType<T(P)> const &f) : ftor_ptr_(f.ftor_ptr_) {}
    ~FunctorType() { delete ftor_ptr_; }
    T operator()(P const &p)
    {
      if (ftor_ptr_)
        return ftor_ptr_->operator()(p);
      return T(p); //this line trigger the error
    }
    C *ftor_ptr_;
  };
  // specialised class templated for fonction pointer
  template <typename TT, typename PP>
  class FunctorType<TT(PP)> : public IFunctorType
  {
  public:
    FunctorType() : fptr_(0) {}
    FunctorType(fp p) : fptr_(p) {}
    FunctorType(FunctorType<T(P)> const &f) : fptr_(f.fptr_) {}
    T operator()(P const &p)
    {
      return fptr_(p);
    }
    fp fptr_;
  };
public:
  Function() : ftor_ptr_(0) {}
  Function(Function<T(P)> const &f) : ftor_ptr_(f.ftor_ptr_) {}
  //Contruct from callable object
  template <typename K>
  Function(K const &p) : ftor_ptr_(new FunctorType<K>(p)) {}
  template <typename K>
  Function<T(P)> &operator=(K const &b)
  {
    if (ftor_ptr_)
      delete ftor_ptr_;
    ftor_ptr_ = new FunctorType<K>(b);
    return *this;
  }
  //Contruct from function pointer
  Function(fp p) : ftor_ptr_(new FunctorType<T(P)>(p)) {}
  Function<T(P)> &operator=(fp p)
  {
    if (ftor_ptr_)
      delete ftor_ptr_;
    ftor_ptr_ = new FunctorType<T(P)>(p);
    return *this;
  }
  //Invoke internal functor pointer
  T operator()(P const &p)
  {
    if (ftor_ptr_)
      return ftor_ptr_->operator()(p);
    return T();
  }
  // Actual pointer to functor
  IFunctorType *ftor_ptr_;
};

那条线应该做什么?这没有多大意义,它尝试将参数转换为返回类型,这注定会失败,因为它确实如此。这不是特定于std::bind的问题,而是处理函数对象的问题:

struct Foo {
  int operator()(const std::string&) { return 0; }
};
Function<int(const std::string &)> b = Foo{}; // oh no!

你应该做与函数指针相同的操作,调用指针并直接返回结果:

T FunctorType<C>::operator()(P const &p)
{
    return ftor_ptr_->operator()(p);
}

但是等等!您可能会问自己:如果ftor_ptr_为空怎么办?好吧,它永远不会为空!切勿在要求其为 null 的上下文中使用它。您的默认构造函数永远不会被使用!以及其他构造函数。

在不赘述更多细节的情况下,您应该能够通过删除不需要的东西来大大简化您的代码,因为您似乎已经考虑了很多永远不会发生的情况。