c++ - C++中的虚拟模板函数

标签 c++ function templates polymorphism virtual

我一直在寻找一种同时使用模板和多态性的方法。这是我的问题的简化版本:

#include <iostream>
#include <vector>
using std::cout;
using std::endl;

//*******************************************************************
//*******************************************************************

struct DerivedStuff1
{
    static void eval() { cout << "evaluating DerivedStuff1" << endl; }
};

struct DerivedStuff2
{
    static void eval() { cout << "evaluating DerivedStuff2" << endl; }
};

//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
    template<typename StuffType> virtual void eval() const = 0;
};

class DerivedClass1 : public BaseClass
{
public:
    template<typename StuffType> virtual void eval() const
    {
        std::cout << "We are in DerivedClass1: ";
        StuffType::eval();
    }
};

class DerivedClass2 : public BaseClass
{
public:
    template<typename StuffType> virtual void eval() const
    {
        std::cout << "We are in DerivedClass2: ";
        StuffType::eval();
    }
};

int main()
{
    BaseClass* c1 = new DerivedClass1;
    c1->eval<DerivedStuff1>();
    c1->eval<DerivedStuff2>();

    BaseClass* c2 = new DerivedClass2;
    c2->eval<DerivedStuff1>();
    c2->eval<DerivedStuff2>();

    return 0;
}

此代码无法编译,因为 C++ 中不允许使用虚拟模板函数。我发现了一些解决这个问题的方法(CRTP 等),但没有一个真正令人满意。没有优雅的方法来解决这个问题吗?

最佳答案

visitor pattern将运行时多态性放在一边,并使运行时多态函数模板成为可能。除了模板化之外,它还有其他合法用途,所以我想你可以说它有点优雅。

您的示例如下所示:

#include <iostream>

class DerivedStuff1 {
  public:
   static void eval() { std::cout << "Evaluating DerivedStuff1\n"; }
};

class DerivedStuff2 {
  public:
   static void eval() { std::cout << "Evaluating DerivedStuff2\n"; }
};

class DerivedClass1; class DerivedClass2;
class BaseClassVisitor {
  public:
    virtual void visit(DerivedClass1&) = 0;
    virtual void visit(DerivedClass2&) = 0;
};

class BaseClass {
  public:
    virtual void accept(BaseClassVisitor& v) = 0;
};

class DerivedClass1 : public BaseClass
{
  public:
    virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};

class DerivedClass2 : public BaseClass
{
  public:
    virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};


template <typename StuffType>
class EvalVisitor : public BaseClassVisitor
{
    virtual void visit(DerivedClass1&) {
        std::cout << "We are in DerivedClass1: ";
        StuffType::eval();
    }
    virtual void visit(DerivedClass2&) {
        std::cout << "We are in DerivedClass2: ";
        StuffType::eval();
    }

};

int main()
{
    EvalVisitor<DerivedStuff1> e1;
    EvalVisitor<DerivedStuff2> e2;

    BaseClass* c1 = new DerivedClass1;

    c1->accept(e1);
    c1->accept(e2);

    BaseClass* c2 = new DerivedClass2;

    c2->accept(e1);
    c2->accept(e2);

    return 0;
}

Demo

当然,Visitor 的所有缺点都适用于此。

关于c++ - C++中的虚拟模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45849394/

相关文章:

c++ - 整数提升、有符号/无符号和 printf

c++ - 寻找一种良好的空间分区数据结构以从中快速生成数百万个原子键

c++ - 类和子类的通用哈希函数

xml - XSL,使用 XML 作为模板的参数

templates - 从go html模板中的父对象访问变量

c++ - OpenCV 无法读取 MP4 视频

c++ - 如果需要,如何使用 Boost 库将具有可变数量参数的处理程序传递给类

c - 当函数的返回类型不允许我这样做时,如何在 C 中返回错误代码?

c++ - 位域的完美转发解决方法

javascript - 在javascript中将函数分配给变量时识别变量