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

如何为std::any重载[]下标运算符?实现容器元素索引访问

解决std::any容器的索引访问问题

你遇到的核心问题是C++不允许仅返回类型不同的函数重载,所以直接重载operator[]的思路走不通。这里给你两种实用的解决办法:

方案一:模板化的operator[]

直接把operator[]定义成模板函数,让调用方显式指定类型,或者通过上下文自动推导。示例代码如下:

#include <vector>
#include <any>
#include <stdexcept>

struct Container {
    std::vector<std::any> m_container;

    template<typename T>
    void push_back(const T& value) {
        m_container.push_back(value);
    }

    // 模板化的operator[],返回T类型的引用
    template<typename T>
    T& operator[](size_t index) {
        auto* ptr = std::any_cast<T>(&m_container[index]);
        if (!ptr) {
            throw std::bad_any_cast{};
        }
        return *ptr;
    }

    // 常量版本
    template<typename T>
    const T& operator[](size_t index) const {
        auto* ptr = std::any_cast<const T>(&m_container[index]);
        if (!ptr) {
            throw std::bad_any_cast{};
        }
        return *ptr;
    }
};

使用方式:

#include <iostream>

int main() {
    Container c;
    c.push_back(0);
    // 显式指定类型
    std::cout << c[int][0] << std::endl;
    // 或者通过赋值让编译器推导类型
    int val = c[0];
    std::cout << val << std::endl;
}

方案二:返回中间代理类

如果想让语法更贴近原生容器(不用显式写类型),可以让operator[]返回一个代理对象,给代理类实现模板化的转换运算符,让编译器自动推导目标类型。示例代码:

#include <vector>
#include <any>
#include <stdexcept>

struct Container;

// 代理类,负责把std::any转换为目标类型
struct AnyProxy {
    std::any& m_value;

    // 模板转换运算符,支持隐式转换到目标类型
    template<typename T>
    operator T&() {
        auto* ptr = std::any_cast<T>(&m_value);
        if (!ptr) {
            throw std::bad_any_cast{};
        }
        return *ptr;
    }

    // 常量版本
    operator const auto&() const {
        return m_value;
    }
};

struct Container {
    std::vector<std::any> m_container;

    template<typename T>
    void push_back(const T& value) {
        m_container.push_back(value);
    }

    // 返回代理对象
    AnyProxy operator[](size_t index) {
        return {m_container[index]};
    }

    // 常量版本
    const std::any& operator[](size_t index) const {
        return m_container[index];
    }
};

这种方案的使用方式完全符合你的需求:

#include <iostream>

int main() {
    Container c;
    c.push_back(0);
    std::cout << c[0] << std::endl; // 编译器自动推导为int类型
    std::string s = "hello";
    c.push_back(s);
    std::cout << c[1] << std::endl; // 自动推导为std::string
}

注意事项

  • 两种方案在类型不匹配时都会抛出std::bad_any_cast异常,你可以根据需求改成返回std::optional<T>或者其他错误处理逻辑。
  • 代理类方案语法更简洁,但隐式转换可能带来意外(比如不小心转换到错误类型),需要根据实际场景选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 07:48:43