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

如何在C++模板中透明处理std::vector<T>与std::vector<std::shared_ptr<T>>

实现模板函数自动处理std::vector对象与std::shared_ptr元素

你需要让同一个模板算法兼容两种std::vector:一种存储类型T的对象,另一种存储指向T的std::shared_ptr<T>,在模板内部自动区分元素类型,对shared_ptr自动解引用,普通对象则直接使用,且不想让客户端代码复杂化。


方法:利用函数重载实现自动解引用

最简洁且兼容旧标准的方式是通过重载辅助函数,让编译器自动根据元素类型选择对应的处理逻辑,完全不需要客户端额外传参。

完整代码示例:

#include <vector>
#include <memory>

struct S {
    void member() const {}
};

// 处理普通对象的重载:直接返回原对象引用
template <typename T>
const T& deref(const T& val) {
    return val;
}

// 处理std::shared_ptr的重载:返回指针指向的对象引用
template <typename T>
const T& deref(const std::shared_ptr<T>& ptr) {
    return *ptr;
}

void fn(const auto& arr) {
    for (const auto& val : arr) {
        // 自动匹配对应deref重载,无需手动判断类型
        const auto& obj = deref(val);
        obj.member();
    }
}

int main()
{
    std::vector<S> objects;
    std::vector<std::shared_ptr<S>> pointers;

    fn(objects);
    fn(pointers);
}

原理说明

  • 辅助函数deref提供两个重载:一个接收普通对象引用,直接返回;另一个接收std::shared_ptr,返回解引用后的对象引用。
  • 编译器在编译时会根据val的实际类型,自动匹配对应的重载版本,实现透明的解引用逻辑。
  • 客户端调用fn时无需做任何额外处理,完全感受不到内部的类型区分逻辑。

C++17及以上可选方案:if constexpr编译期判断

如果使用C++17及以上标准,也可以直接通过编译期类型判断实现,无需额外重载函数:

#include <vector>
#include <memory>
#include <type_traits>

struct S {
    void member() const {}
};

// 类型 trait:判断是否为std::shared_ptr
template <typename T>
struct is_shared_ptr : std::false_type {};

template <typename T>
struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};

template <typename T>
constexpr bool is_shared_ptr_v = is_shared_ptr<T>::value;

void fn(const auto& arr) {
    for (const auto& val : arr) {
        const auto& obj = [&]() -> const S& {
            // 编译时判断类型,选择对应的分支
            if constexpr (is_shared_ptr_v<std::decay_t<decltype(val)>>) {
                return *val;
            } else {
                return val;
            }
        }();
        obj.member();
    }
}

int main()
{
    std::vector<S> objects;
    std::vector<std::shared_ptr<S>> pointers;

    fn(objects);
    fn(pointers);
}

这种方式在lambda内部通过if constexpr实现编译期分支选择,同样不会影响客户端代码的简洁性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 06:03:13