如何判断传递给C++模板的参数是否为shared_ptr?
这个问题其实很好解决,我们可以借助C的**类型特性(type traits)**来判断一个类型是不是std::shared_ptr。下面给你两种实用的实现方式,分别适配不同的C版本:
方式一:C++20及以上版本(推荐)
从C++20开始,标准库新增了std::is_specialization_of,可以直接用来判断一个类型是否是某个模板的特化版本。我们可以用它快速识别std::shared_ptr,直接把这个判断加到你的模板函数里就行:
#include <memory> #include <type_traits> #include <iostream> #include <vector> template <class T> size_t get_size(T const &vec) { if constexpr (std::is_pointer_v<T>) { std::cout << "pointer" << std::endl; return vec->size(); } // 新增shared_ptr判断分支 else if constexpr (std::is_specialization_of_v<T, std::shared_ptr>) { std::cout << "shared_ptr" << std::endl; return vec->size(); } else { std::cout << "not pointer or shared_ptr" << std::endl; return vec.size(); } } // 测试示例 int main() { std::vector<int> v{1,2,3}; get_size(v); // 输出:not pointer or shared_ptr auto raw_ptr = &v; get_size(raw_ptr); // 输出:pointer auto sp = std::make_shared<std::vector<int>>({1,2,3}); get_size(sp); // 输出:shared_ptr return 0; }
方式二:兼容C11/C17版本
如果你的项目还在使用C++20之前的标准,我们可以手动实现一个类型特性来识别std::shared_ptr:
#include <memory> #include <type_traits> #include <iostream> #include <vector> // 基础模板:默认不是shared_ptr template <typename T> struct is_shared_ptr : std::false_type {}; // 特化模板:匹配任意类型参数的std::shared_ptr template <typename U> struct is_shared_ptr<std::shared_ptr<U>> : std::true_type {}; // 方便使用的变量模板,简化调用 template <typename T> constexpr bool is_shared_ptr_v = is_shared_ptr<T>::value; template <class T> size_t get_size(T const &vec) { if constexpr (std::is_pointer_v<T>) { std::cout << "pointer" << std::endl; return vec->size(); } // 使用我们自己实现的类型特性判断 else if constexpr (is_shared_ptr_v<T>) { std::cout << "shared_ptr" << std::endl; return vec->size(); } else { std::cout << "not pointer or shared_ptr" << std::endl; return vec.size(); } } // 测试示例 int main() { std::vector<int> v{1,2,3}; get_size(v); auto raw_ptr = &v; get_size(raw_ptr); auto sp = std::make_shared<std::vector<int>>({1,2,3}); get_size(sp); return 0; }
补充说明
std::shared_ptr本身并不是原生指针类型,所以std::is_pointer_v<T>对它会返回false,不会和你之前的指针判断分支冲突,必须单独加一个分支处理。- 手动实现类型特性的核心是模板特化:我们针对
std::shared_ptr<U>这个模板特化了is_shared_ptr结构体,让它继承std::true_type,这样就能识别任何类型参数的std::shared_ptr。
备注:内容来源于stack exchange,提问作者newandlost
相关产品推荐
相关产品推荐

