模板化Visitor Pattern实现求助:虚模板成员函数不可用
模板化访问者模式实现问题:虚模板成员函数的替代方案
这是对《No user defined conversion when using standard variants and visitor pattern》的跟进需求。我需要实现模板化版本的访问者模式,但要求Visitable类不能是模板类(否则可以用CRTP解决问题)。当前的核心矛盾在于:accept函数需要具备虚函数的动态分发能力,但C++不允许虚模板成员函数,导致通过Visitable*基类指针调用accept时,只会执行基类中抛出异常的默认实现,无法正确匹配到子类DoubleVisitable或StringVisitable的accept逻辑。
以下是当前的代码实现:
#include <variant> #include <iostream> class Visitable // 要求这个类不能是模板类!否则可以用CRTP解决问题 { public: virtual ~Visitable() = default; template<typename Visitor> /*virtual*/ double accept(Visitor* visitor) // 这里不能加virtual { 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); // 我希望能正常执行这段代码: Visitable* doubleV = new DoubleVisitable(); doubleV->accept(&visitor); delete doubleV; return 1; }
我的核心需求是:让Visitable*指针调用accept时,不再抛出异常,而是正确分发到对应子类的accept实现,进而匹配到SubVisitor中对应的process函数处理逻辑。
内容的提问来源于stack exchange,提问作者Vero
相关产品推荐
相关产品推荐

