You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

模板化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 17:30:44