Передача дочерних классов базового класса в конструктор с использованием CRTP? - PullRequest
0 голосов
/ 26 октября 2019

У меня есть следующий базовый класс:

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();
};

Я хочу иметь возможность передать выражение Expression в конструктор Add, поэтомуЯ могу быть в состоянии вызвать Add(Add(Literal(10),Literal(20)),Literal(30)).eval() в результате 50. Это возможно в C ++ 11?

1 Ответ

0 голосов
/ 27 октября 2019

Это работает, если вы делаете 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<Literal, Literal> и т. Д.

...