简体   繁体   English

C ++函子(映射)

[英]C++ functor (mapping)

I have created a class either<l, r> much like Haskell's Either ab . 我创建了一个类, either<l, r>类似于Haskell的Either ab either<l, r> I have also implemented a function map directly in the class; 我还直接在该类中实现了功能map this is what the code looks like: 代码如下所示:

template<typename l, typename r>
class either 
{
  template<typename b>
  either<l, b> map(const std::function<b (r)> &f)
  {
    // ...
  }
};

Now I want to isolate the map function in order to create an abstract base class called functor 现在,我想隔离map函数,以创建一个称为functor的抽象基类。

template<typename a, template <a> class derived>
class functor
{
public:
  virtual ~functor();

  template<typename b>
  derived<b> map(const std::function<b (a)> &f) = nullptr;
};

either would inherit this class: either都将继承此类:

class either : functor<r, either<l, r>>

however this is invalid C++ as template member functions can not be virtual. 但是,这是无效的C ++,因为模板成员函数不能是虚拟的。

Moreover, I have attempted to test if <r, either<l, r>> can match <a, derived<a>> in functor<r, either<l, r>> (or any other template for that matter) but haven't been able to since it has two template parameters. 而且,我试图测试<r, either<l, r>>可以与functor<r, either<l, r>> (或其他任何模板)中的<a, derived<a>>匹配<a, derived<a>>但是由于它具有两个模板参数,因此无法实现。 Also note that other derived classes of functor might have different numbers of template arguments that are irrelevant to functor. 还要注意,函子的其他派生类可能具有与函子无关的不同数量的模板参数。

Can the functor base class be expressed in C++ templates? 函子基类可以用C ++模板表示吗?

Since you are using the curiously recurring template pattern, there's no need for virtual functions. 由于您使用的是奇怪的重复发生的模板模式,因此不需要虚拟函数。 Your goal of dispatching to the method of the derived class can be achieved directly from the base class. 您可以直接从基类中实现派生到派生类的方法的目标。

A typical implementation would be the following : 一个典型的实现如下:

#include <iostream>
#include <functional>

using namespace std;

template<typename a, class derived>
class functor
{
public:
    // You have to define the destructor
    virtual ~functor() {}

    template<typename b>
    // The full type of the derived class is known
    derived map(const std::function<b(a)> &f)
    {
        // Here you take advantage of the CRTP
        return static_cast<derived*>(this)->map(f);
    }
};

template<typename l, typename r>
// You have to put public as inheritance access level
class either : public functor<r, either<l, r>>
{ // The way you want to inherit implies that the base has no 
  // template template parameter, just template parameters !!
public:
    template<typename b>
    either<l, b> map(const std::function<b(r)> &f)
    {
        cout << "In derived" << endl;
        return  either<l, b>();
    }
};

int main() 
{
    // pointer to base class points to a derived object
    functor<int, either<int, int>> *ff = new either<int, int>();
    // map function will call the method of the derived class
    ff->map<int>([](int k){ return 1; });

    return 0;
}

I took the liberty of pointing some things out in the comments. 我乐于在评论中指出一些事情。 HTH HTH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM