I have created a class either<l, r>
much like Haskell's Either ab
. I have also implemented a function map
directly in the class; 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
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:
class either : functor<r, either<l, r>>
however this is invalid C++ as template member functions can not be virtual.
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. 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?
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.