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

std::visit的使用与误用:类继承场景下的问题及方案探讨

关于std::visit结合继承实现访问者模式的问题

近期我频繁在代码中使用访问者模式,之前习惯经典实现方式,自从C++17引入std::variant后,我更倾向于结合std::visit来实现该模式,但发现std::visit存在局限性。

我知道std::visit接受lambda,或是实现了variant所有类型operator()重载的结构体/类。但我发现一个问题:当父类实现了所有operator()重载时,子类调用std::visit能正常工作;但如果子类添加了与variant类型无关的operator()重载,代码就会报错,提示std::visit要求访问者必须穷举所有类型。

报错代码示例

#include <iostream>
#include <variant>
#include <string>
#include <vector>

using TYPE = std::variant<int, double, float, std::string, std::monostate>;
class parentVisitor {
public:
    parentVisitor() = default;
    std::string operator()(const int value) const {return std::to_string(value);}
    std::string operator()(const double value) const {return std::to_string(value);}
    std::string operator()(const float value) const {return std::to_string(value);}
    std::string operator()(std::string value) const {return value;}
    std::string operator()(std::monostate) const {return "";}
};

class childVisitor : public parentVisitor {
private:
    TYPE m_value;
public:

    // 下面这行代码会引发错误!
    void operator()(std::vector<int> value) const {}


    explicit childVisitor(TYPE value) : m_value(std::move(value)) {};

    void printValue() {
        const std::string text = std::visit(*this, m_value);
        std::cout << text << std::endl;
    }
};

int main() {
    std::string text = "CPP";
    childVisitor visitor(text);
    visitor.printValue();
    return 0;
}

错误信息

error: static assertion failed due to requirement 'is_invocable_v<childVisitor &, int &>': `std::visit` requires the visitor to be exhaustive.
  611 |     static_assert(is_invocable_v<_Visitor, _Values...>, "`std::visit` requires the visitor to be exhaustive.");

我尝试在父类中实现visit_parent方法,让子类调用该方法来规避问题,修改后的代码可以正常运行。现在想咨询以下问题:

  • 这个规避方案是否合理?
  • 还有哪些基于类继承的访问者模式实现方式?

内容的提问来源于stack exchange,提问作者Sukrit Ghorai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 21:07:12