具有变量 return 类型的 C++ 访问者模式
C++ Visitor Pattern with variable return types
我有以下设置:
class IVisitor{
public:
virtual SomeType visit(IVisitable& visitable) = 0;
};
class IVisitable{
public:
virtual SomeType accept(IVisitor& visitor) = 0;
};
class ConcreteVisitor : public IVisitor{
public:
SomeType visit(IVisitable& visitable) override {
return calculateSomeStuff();
}
};
class ConcertVisitable : public IVisitable{
public:
SomeType accept(IVisitor& visitor) override {
return visitor.visit(*this);
}
};
但我希望不同的访问者 return 具有不同的类型。为此,IVisitable::accept()
还应该 return 不同的类型。
这将导致以下(不正确的)代码:
template <typename R>
class IVisitor{
public:
virtual R visit(IVisitable& visitable) = 0;
};
class IVisitable{
public:
template <typename R>
virtual R accept(IVisitor<R>& visitor) = 0;
};
class ConcreteVisitorOne : public IVisitor<int>{
public:
int visit(IVisitable& visitable) override {
return calculateSomeStuff();
}
};
class ConcreteVisitorTwo : public IVisitor<bool>{
public:
bool visit(IVisitable& visitable) override {
return calculateSomeStuff();
}
};
class ConcertVisitable : public IVisitable{
public:
int accept<int>(IVisitor<int>& visitor) override {
return visitor.visit(*this);
}
};
不幸的是,这在 C++ 中是不可能的,因为 虚拟 函数 IVistitable::accept()
无法模板化。
有人知道解决此限制的方法吗?
几个选项:
不要return任何东西,处理访问者内部的值。访问者可以完全自由地存储或处理任何 return 值和类型。
Return 可变类型(std::any
或 std::variant
)。请注意,使用它们需要您找出实际类型,这可能与您原来的问题有点相似。
继承多个IVisitor<>
接口。这甚至可能是最简单的方法,尽管它不一定很优雅。
另一种选择是切换到 std::variant
(C++17) 而不是双重分派:
int i = std::visit([](auto& v){ return 42;}, some_variant);
bool b = std::visit([](auto& v){ return false;}, some_variant);
我有以下设置:
class IVisitor{
public:
virtual SomeType visit(IVisitable& visitable) = 0;
};
class IVisitable{
public:
virtual SomeType accept(IVisitor& visitor) = 0;
};
class ConcreteVisitor : public IVisitor{
public:
SomeType visit(IVisitable& visitable) override {
return calculateSomeStuff();
}
};
class ConcertVisitable : public IVisitable{
public:
SomeType accept(IVisitor& visitor) override {
return visitor.visit(*this);
}
};
但我希望不同的访问者 return 具有不同的类型。为此,IVisitable::accept()
还应该 return 不同的类型。
这将导致以下(不正确的)代码:
template <typename R>
class IVisitor{
public:
virtual R visit(IVisitable& visitable) = 0;
};
class IVisitable{
public:
template <typename R>
virtual R accept(IVisitor<R>& visitor) = 0;
};
class ConcreteVisitorOne : public IVisitor<int>{
public:
int visit(IVisitable& visitable) override {
return calculateSomeStuff();
}
};
class ConcreteVisitorTwo : public IVisitor<bool>{
public:
bool visit(IVisitable& visitable) override {
return calculateSomeStuff();
}
};
class ConcertVisitable : public IVisitable{
public:
int accept<int>(IVisitor<int>& visitor) override {
return visitor.visit(*this);
}
};
不幸的是,这在 C++ 中是不可能的,因为 虚拟 函数 IVistitable::accept()
无法模板化。
有人知道解决此限制的方法吗?
几个选项:
不要return任何东西,处理访问者内部的值。访问者可以完全自由地存储或处理任何 return 值和类型。
Return 可变类型(
std::any
或std::variant
)。请注意,使用它们需要您找出实际类型,这可能与您原来的问题有点相似。继承多个
IVisitor<>
接口。这甚至可能是最简单的方法,尽管它不一定很优雅。
另一种选择是切换到 std::variant
(C++17) 而不是双重分派:
int i = std::visit([](auto& v){ return 42;}, some_variant);
bool b = std::visit([](auto& v){ return false;}, some_variant);