使用 CRTP 将 Base Class 的子 Classes 传递给构造函数?
Passing Child Classes of a Base Class to a constructor using CRTP?
我有以下基础Class:
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 的 Classes:
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 中可能吗?
如果您将 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>
等等。
我有以下基础Class:
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 的 Classes:
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 中可能吗?
如果您将 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>
等等。