【问题标题】:Passing Child Classes of a Base Class to a constructor using CRTP?使用 CRTP 将基类的子类传递给构造函数?
【发布时间】:2019-10-26 19:21:12
【问题描述】:

我有以下基类:

class BaseVisitor
{
public:
    virtual ~BaseVisitor() {};
};

template <class T>
class Visitor
{
public:
    virtual void visit(T&) = 0;
};

template <class Visitable>
class Expression
{
public:

    template <typename T>
    void accept(T& visitor)
    {
        visitor.visit(static_cast<Visitable&>(*this));
    }
    void print() {
        static_cast<Visitable*>(this)->print();
    }
    void eval() {
        static_cast<Visitable*>(this)->eval();
    }

};

以及继承自 Expression 的类:

class Literal : public Expression<Literal>
{

protected:
    int value = 0;
public:

    Literal() {};
    Literal(int x);
    std::string print();

    int eval();
};

class Add : public Expression<Add>
{
protected:
    Literal lhs;
    Literal rhs;

public:

    Add(Literal left, Literal  right);
    void print();
    int eval();
};

我希望能够将表达式传递给 Add 构造函数,这样我就可以调用 Add(Add(Literal(10),Literal(20)),Literal(30)).eval() 得到 50。 这在 C++11 中可行吗?

【问题讨论】:

  • 是的,这在 C++ 中是可能的,但很复杂。您要查找的搜索词是expression templates(本文在底部列出了一些您可以研究的示例)。

标签: c++ crtp


【解决方案1】:

如果您将 Add 设为模板而不是硬编码其左右参数必须是字面量,则它可以工作:

template<typename L, typename R>
class Add : public Expression<Add<L,R>>
{
protected:
    L lhs;
    R rhs;

public:

    Add(L left, R  right) : lhs(left), rhs(right) {}
    int eval() { return lhs.eval() + rhs.eval(); }
};

编译 Add(Add(Literal(10),Literal(20)),Literal(30)).eval() 然后需要 C++17。如果你想让它与 C++11 一起工作,你需要编写一个类似于 std::make_pair 的包装函数,以避免编写 Add&lt;Literal, Literal&gt; 等等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-04
    • 2014-12-25
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-25
    相关资源
    最近更新 更多