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

C++自定义pair类如何实现直接通过[]运算符访问输出内部元素

问题背景

我实现了一个功能类似std::pair的自定义bpair结构体,初始实现代码如下:

template<typename firstType,typename secondType> 
struct bpair{ 
    firstType first;
    secondType second;

    bpair(firstType firstNew,secondType secondNew) {
        first = firstNew;
        second = secondNew;
    }

    variant<firstType,secondType> operator[](size_t index) {
        if(index == 0) {
            return first;
        }
        return second;
    }
}; 

现有测试调用代码:

bpair<string,int> hey = bpair(string("hi"),34);
cout << get<string>(hey[0]);

目前[]运算符返回variant类型,必须通过get模板函数取出值才能正常输出,想要实现直接通过[]访问元素,支持如下调用写法:

cout << hey[0];
实现方案

首先明确核心限制:C++中函数返回值类型必须在编译阶段确定,如果传入[]的索引是运行时才能确定值的变量(比如随机生成的0/1),没有办法在编译期预知返回的是firstType还是secondType,这种场景下返回variant是合理的实现方式。要实现直接输出hey[0],有两种可选方案,优先选改动最小的方案1即可。

方案1:重载variant的流输出运算符(兼容运行时索引,改动最小)

不需要修改现有bpair的结构体逻辑,只要在全局或者bpair所在命名空间添加variant的流输出重载,内部通过std::visit自动匹配当前存储值的类型完成输出:

#include <variant>
#include <ostream>

template<typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::variant<T1, T2>& v) {
    std::visit([&os](const auto& val) {
        os << val;
    }, v);
    return os;
}

添加这段代码后,不管索引是编译期写死的0/1字面量,还是运行时动态计算的索引值,都可以直接通过cout << hey[0]的写法输出内容,不需要手动调用get。

方案2:编译期常量索引重载(零开销返回元素引用)

如果所有访问场景的索引都是写死的0、1常量,不需要动态传索引,可以在C++23及以上标准中新增模板化的[]运算符重载,编译期直接返回对应元素的引用,没有variant的额外开销:

#include <utility>
#include <variant>

template<typename firstType,typename secondType> 
struct bpair{ 
    firstType first;
    secondType second;

    // 改用初始化列表提升构造效率
    bpair(firstType firstNew,secondType secondNew): first(std::move(firstNew)), second(std::move(secondNew)) {}

    // C++23及以上支持模板化operator[]
    template<size_t Index>
    auto& operator[](std::integral_constant<size_t, Index>) {
        if constexpr (Index == 0) {
            return first;
        } else if constexpr (Index == 1) {
            return second;
        } else {
            static_assert(Index < 2, "bpair index out of bounds");
        }
    }

    // 保留原有运行时索引逻辑
    std::variant<firstType,secondType> operator[](size_t index) {
        if(index == 0) {
            return first;
        }
        return second;
    }
};

注意这个方案如果要走编译期返回引用的逻辑,调用时需要传入编译期常量作为参数,写法为hey[std::integral_constant<size_t, 0>{}],直接写hey[0]会优先匹配原有运行时索引的重载,还是需要配合方案1的流重载才能直接输出,因此日常使用优先选方案1即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:27:17