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

能否从函数中根据条件返回不同容器的迭代器对?

可行方案:返回不同容器的迭代器对

一、直接可行,两种主流实现方式

1. C++17及以上:使用std::variant(推荐)

std::variant是标准库提供的类型安全联合体,可直接包装两种不同的迭代器对类型,返回值类型明确且无额外性能损耗。

代码示例:

#include <variant>
#include <vector>
#include <list>
#include <utility>
#include <iostream>

// 定义示例容器类型
template<typename T>
using C = std::vector<T>;
template<typename T>
using D = std::list<T>;

template<typename T>
auto get_iter_pair(bool use_container_c, C<T>& c, D<T>& d) {
    // 定义两种迭代器对类型的variant
    using CIterPair = std::pair<typename C<T>::iterator, typename C<T>::iterator>;
    using DIterPair = std::pair<typename D<T>::iterator, typename D<T>::iterator>;
    using IterPairVariant = std::variant<CIterPair, DIterPair>;

    return use_container_c ? 
        IterPairVariant{std::make_pair(c.begin(), c.end())} :
        IterPairVariant{std::make_pair(d.begin(), d.end())};
}

// 使用示例
int main() {
    C<int> vec = {1, 2, 3};
    D<int> lst = {4, 5, 6};

    // 获取vector的迭代器对并遍历
    auto pair = get_iter_pair(true, vec, lst);
    std::visit([](auto&& p) {
        for (auto it = p.first; it != p.second; ++it) {
            std::cout << *it << " ";
        }
        std::cout << "\n";
    }, pair);

    // 获取list的迭代器对并遍历
    pair = get_iter_pair(false, vec, lst);
    std::visit([](auto&& p) {
        for (auto it = p.first; it != p.second; ++it) {
            std::cout << *it << " ";
        }
        std::cout << "\n";
    }, pair);
    
    return 0;
}

使用时通过std::visit分发处理两种迭代器类型,逻辑清晰且符合标准库规范。

2. 多态迭代器包装器(透明接口)

如果需要更接近普通迭代器的使用体验(无需std::visit),可实现一个多态包装器,封装不同类型的迭代器并提供统一接口。代价是虚函数调用的性能损耗和堆内存分配。

代码示例:

#include <vector>
#include <list>
#include <memory>
#include <utility>
#include <iostream>

// 抽象迭代器基类
template<typename T>
class AnyIterator {
public:
    virtual ~AnyIterator() = default;
    virtual T& operator*() = 0;
    virtual const T& operator*() const = 0;
    virtual AnyIterator& operator++() = 0;
    virtual bool operator!=(const AnyIterator& other) const = 0;
    virtual std::unique_ptr<AnyIterator> clone() const = 0;
};

// 具体迭代器包装类
template<typename Iter>
class IteratorWrapper : public AnyIterator<typename std::iterator_traits<Iter>::value_type> {
private:
    Iter m_iter;
public:
    using ValueType = typename std::iterator_traits<Iter>::value_type;

    explicit IteratorWrapper(Iter iter) : m_iter(std::move(iter)) {}

    ValueType& operator*() override { return *m_iter; }
    const ValueType& operator*() const override { return *m_iter; }
    IteratorWrapper& operator++() override { ++m_iter; return *this; }
    bool operator!=(const AnyIterator<ValueType>& other) const override {
        const auto* wrapper = dynamic_cast<const IteratorWrapper*>(&other);
        return wrapper ? (m_iter != wrapper->m_iter) : false;
    }
    std::unique_ptr<AnyIterator<ValueType>> clone() const override {
        return std::make_unique<IteratorWrapper>(m_iter);
    }
};

// 迭代器对的包装结构,支持范围for
template<typename T>
struct AnyIterPair {
    std::unique_ptr<AnyIterator<T>> first;
    std::unique_ptr<AnyIterator<T>> last;

    struct RangeIter {
        std::unique_ptr<AnyIterator<T>> current;
        std::unique_ptr<AnyIterator<T>> end;

        bool operator!=(const RangeIter& other) const {
            return *current != *other.end;
        }
        T& operator*() { return **current; }
        RangeIter& operator++() { ++*current; return *this; }
    };

    RangeIter begin() const { return {first->clone(), last->clone()}; }
    RangeIter end() const { return {last->clone(), last->clone()}; }
};

// 定义示例容器类型
template<typename T>
using C = std::vector<T>;
template<typename T>
using D = std::list<T>;

template<typename T>
AnyIterPair<T> get_iter_pair(bool use_container_c, C<T>& c, D<T>& d) {
    if (use_container_c) {
        return {
            std::make_unique<IteratorWrapper<typename C<T>::iterator>>(c.begin()),
            std::make_unique<IteratorWrapper<typename C<T>::iterator>>(c.end())
        };
    } else {
        return {
            std::make_unique<IteratorWrapper<typename D<T>::iterator>>(d.begin()),
            std::make_unique<IteratorWrapper<typename D<T>::iterator>>(d.end())
        };
    }
}

// 使用示例
int main() {
    C<int> vec = {1, 2, 3};
    D<int> lst = {4, 5, 6};

    auto pair = get_iter_pair(true, vec, lst);
    for (int val : pair) {
        std::cout << val << " ";
    }
    std::cout << "\n";

    pair = get_iter_pair(false, vec, lst);
    for (int val : pair) {
        std::cout << val << " ";
    }
    std::cout << "\n";
    
    return 0;
}

这种方式可像普通迭代器对一样直接用于范围for循环,对调用者更透明。

二、补充说明

  • 如果两个容器都是连续内存类型(如vector、array),C++20的std::span也是可选方案,但它仅支持随机访问迭代器,无法适配list这类非连续容器。
  • 优先选择std::variant方案,它属于标准库、性能更优且类型安全;多态包装器适合需要完全透明迭代器接口的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 14:14:55