这是对使用标准变量和访问者模式时无用户定义转换的后续操作
我需要实现一个visitor pattern的模板版本,如下所示,但是看起来accept
函数必须是虚拟的,这是不可能的。你能帮助我吗?
#include <variant>
#include <iostream>
class Visitable //I need this to be non-templated (no template for Visitable!!): Otherwise I could use CRTP to solve this issue.
{
public:
virtual ~Visitable() = default;
template<typename Visitor>
/*virtual*/ double accept(Visitor* visitor) //I can't do virtual here.
{
throw("I don't want to end up here");
};
protected:
Visitable() = default;
};
struct DoubleVisitable : public Visitable
{
template<typename Visitor>
double accept(Visitor* visitor)
{
return visitor->visit(*this);
};
double m_val = 1.0;
};
struct StringVisitable : public Visitable
{
template<typename Visitor>
double accept(Visitor* visitor)
{
return visitor->visit(*this);
};
double m_val = 0.0;
};
template<typename... args>
class Visitor
{
public:
virtual ~Visitor() = default;
virtual double visit(typename std::variant<args...> visitable)
{
auto op = [this](typename std::variant<args...> visitable) -> double { return this->apply(visitable); };
return std::visit(std::ref(op), visitable);
}
virtual double apply(typename std::variant<args...> visitable) = 0;
Visitor() = default;
};
class SubVisitor : public Visitor<DoubleVisitable, StringVisitable>
{
public:
virtual ~SubVisitor() = default;
SubVisitor() : Visitor<DoubleVisitable, StringVisitable>() {};
virtual double apply(std::variant<DoubleVisitable, StringVisitable> visitable) override
{
return std::visit(
[this](auto&& v){return process(v);},
visitable
);
};
virtual double process(const StringVisitable& visitable)
{
std::cout << "STRING HANDLED" << std::endl;
return 0.0;
}
virtual double process(const DoubleVisitable& visitable)
{
std::cout << "DOUBLE HANDLED" << std::endl;
return 1.0;
}
};
int main(int argc, char* argv[])
{
SubVisitor visitor;
DoubleVisitable visitable;
visitable.accept(&visitor);
//I want to be doing this:
Visitable* doubleV = new DoubleVisitable();
doubleV->accept(&visitor);
delete doubleV;
return 1;
}
代码在这里Link。你能不能帮我使这个不抛出,但折叠到右边的子类DoubleVisitable
或StringVisitable
。它看起来像我需要虚拟模板成员函数,这是不可能的,因为这里提到Can a class member function template be virtual?
2条答案
按热度按时间gwbalxhn1#
在C++中,没有
template
virtual
函数。这是不存在的。您可以做的是:std::variant<>
实现而不是继承。vsikbqxv2#
问题中说
Visitable
不能是模板。但是允许它从模板类 * 继承 * 吗?你知道所有可能的访问者吗?如果是,你可以添加一个新的模板类,Visitable
从它继承,并为所有访问者声明虚方法:在上面的代码中,我们只列出了
SubVisitor
,但是AcceptMethods
是可变的,所以它可能是typedef AcceptMethods<A, B, C, D, AndSoOn> AllAcceptMethods;
。然后,我们添加另一个模板类
WithGenericAcceptMethod
,其目的是通过调用模板方法acceptT
来实现由AcceptMethods
声明的accept
方法:这个类的第一个参数是一个
This
参数,这符合CRTP的精神。然后我们可以让特定的可访问类继承WithGenericAcceptMethod
,并实现模板acceptT
方法: