当前位置: 首页 > news >正文

C++高级应用(1)-类型擦除(Type Erasure)和模板特化(Template Specialization)详解

类型擦除(Type Erasure)和模板特化(Template Specialization)是 C++ 中两个非常强大的泛型编程机制。它们可以分别用于构建灵活的抽象接口和控制模板行为。我们将分别讲解这两个机制的原理用法以及结合应用示例


一、类型擦除(Type Erasure)

原理概念

类型擦除是一种设计技巧,用于隐藏类型信息而保留其行为,使得用户代码可以操作任意类型的对象,只要它满足某些接口要求。例如:

  • 标准库中的 std::function
  • std::any / std::variant
  • 自定义泛型容器 / 接口桥接器

示例:模拟 std::function 的类型擦除

实现一个 AnyCallable,它可以存储任意可调用对象(函数、lambda、仿函数等)。

#include <iostream>
#include <memory>class AnyCallable {
public:// 构造函数模板,接受任意可调用对象template<typename Callable>AnyCallable(Callable func) : obj_(std::make_unique<Model<Callable>>(std::move(func))) {}// 调用包装的函数void operator()() const {obj_->call();}private:struct Concept {virtual ~Concept() = default;virtual void call() const = 0;};template<typename Callable>struct Model : Concept {Callable func_;Model(Callable f) : func_(std::move(f)) {}void call() const override {func_();}};std::unique_ptr<Concept> obj_;
};int main() {AnyCallable f1 = []() { std::cout << "Hello Lambda\n"; };AnyCallable f2 = []() { std::cout << "Another function\n"; };f1();f2();return 0;
}

重点:

  • Concept 是一个抽象基类(接口)
  • Model<T> 是具体类型实现,模板化实现任意类型
  • 所有类型都被“擦除”成 Concept* 接口操作

二、模板特化(Template Specialization)

模板特化是控制模板行为的工具,可以为特定类型或条件提供特殊实现

分类:

  • 全特化(Full Specialization)
  • 偏特化(Partial Specialization)
  • SFINAE/std::enable_if/constexpr if 条件特化

示例 1:全特化

template<typename T>
struct Printer {void print() { std::cout << "Generic type\n"; }
};template<>
struct Printer<int> {void print() { std::cout << "Int specialization\n"; }
};int main() {Printer<double>().print();  // GenericPrinter<int>().print();     // Int specialization
}

示例 2:偏特化

template<typename T1, typename T2>
struct Pair {};template<typename T>
struct Pair<T, int> {void print() { std::cout << "Second is int\n"; }
};int main() {Pair<double, int>().print();  // Second is int
}

三、二者结合:类型擦除 + 模板特化示例

用一个统一接口 PointContainer 来封装不同类型的点云容器(如 std::vector<Eigen::Vector3d>pcl::PointCloud<pcl::PointXYZ>等),并通过特化获取其大小、访问等。

示例:简化版点容器类型擦除 + 特化访问器

#include <iostream>
#include <vector>
#include <memory>
#include <Eigen/Dense>// 类型擦除接口
class IPointContainer {
public:virtual ~IPointContainer() = default;virtual size_t size() const = 0;virtual Eigen::Vector3d point(size_t i) const = 0;
};// 模板实现(通过特化支持不同容器)
template<typename T>
class PointContainerImpl : public IPointContainer {
public:PointContainerImpl(T data) : data_(std::move(data)) {}size_t size() const override {return traits<T>::size(data_);}Eigen::Vector3d point(size_t i) const override {return traits<T>::point(data_, i);}private:T data_;
};// traits 特化
template<typename T>
struct traits;template<>
struct traits<std::vector<Eigen::Vector3d>> {static size_t size(const std::vector<Eigen::Vector3d>& v) {return v.size();}static Eigen::Vector3d point(const std::vector<Eigen::Vector3d>& v, size_t i) {return v[i];}
};// 使用统一接口
int main() {std::vector<Eigen::Vector3d> pts = {{1, 2, 3},{4, 5, 6}};std::unique_ptr<IPointContainer> container = std::make_unique<PointContainerImpl<std::vector<Eigen::Vector3d>>>(pts);for (size_t i = 0; i < container->size(); ++i) {std::cout << "Point: " << container->point(i).transpose() << "\n";}
}

总结对比:

特性类型擦除模板特化
目的抽象接口,隐藏实现类型为特定类型提供自定义实现
实现机制虚函数 + 模板组合template<> / std::enable_if
灵活性高,运行时处理多种类型高,编译期选择不同实现
成本有运行时开销(虚函数)无运行时开销,编译期展开
使用场景插件式架构、多态容器、API封装数值类型优化、特例算法、高性能分支

相关文章:

  • aksharetools:大模型智能体框架agno可直接获取A股金融数据
  • [Mac] 开发环境部署工具ServBay 1.12.2
  • React Hooks 必须在组件最顶层调用的原因解析
  • 【机器人】复现 WMNav 具身导航 | 将VLM集成到世界模型中
  • Spring Boot 项目的计算机专业论文参考文献
  • 创建react工程并集成tailwindcss
  • React中useState中更新是同步的还是异步的?
  • 文件读取漏洞路径与防御总结
  • c++重要知识点汇总(不定期更新)
  • 机器学习 day04
  • leetcode 239. 滑动窗口最大值
  • gcc/g++常用参数
  • linux-yum-异常
  • 【Docker】docker compose和docker swarm区别
  • UDP的单播组播与广播
  • Vue框架
  • vue2 切换主题色以及单页面好使方法
  • 【HCIA】聚合VLAN
  • QT+Visual Studio 配置开发环境教程
  • Java—异常体系
  • 人民网:激发博物馆创新活力,让“过去”拥有“未来”
  • 80后女博士黄双燕拟提名为内蒙古盟市政府(行署)副职人选
  • 英德宣布开发射程超2000公里导弹,以防务合作加强安全、促进经济
  • 中拉互联网发展与合作论坛在西安开幕
  • 丹麦外交大臣拉斯穆森将访华
  • 中日东三省问题的源起——《1905年东三省事宜谈判笔记》解题