原来 C++ 这么简单:每日十题轻松学 (Day 7 CRTP 与类型萃取篇)

📘 本篇专注两个深度主题:CRTP(Curiously Recurring Template Pattern)奇异递归模板模式类型萃取(type traits)技巧。这是现代 C++ 泛型设计和高性能库实现的核心技术。我们以实用出发,通过精炼讲解 + 具体可跑的示例,带你理解底层原理并学会实战使用。


在这里插入图片描述

🎯 今日目标

核心技术掌握重点
CRTP 模式学会如何通过模板实现静态多态与接口内联展开
类型萃取 traits理解 std::is_xxx、enable_if 的构造原理与用法
高级组合将两者结合设计更灵活可配置的类型行为系统

✅ 一、CRTP 模式:静态多态与行为注入

🔸 结构示例

template<typename Derived>
class Base {
public:
    void interface() {
        static_cast<Derived*>(this)->implementation();
    }
};

class Foo : public Base<Foo> {
public:
    void implementation() {
        std::cout << "Foo::implementation()" << std::endl;
    }
};

int main() {
    Foo f;
    f.interface();  // 输出 Foo::implementation()
}

📌 本质说明:

  • 基类模板以派生类为参数,构成编译期绑定的多态结构
  • 避免虚函数开销,允许内联展开,适用于性能敏感场景

📌 使用场景:

  • STL 算法、Eigen 数学库
  • 状态机框架、策略注入系统

✅ 二、类型萃取(traits):让类型具备“可判定性”

🔸 自定义 is_pointer 判断逻辑

template<typename T>
struct is_pointer {
    static const bool value = false;
};

template<typename T>
struct is_pointer<T*> {
    static const bool value = true;
};

std::cout << is_pointer<int>::value;   // 输出 0
std::cout << is_pointer<int*>::value;  // 输出 1

📌 本质说明:

  • 类型萃取用于“在编译期判断某类型是否满足某种结构”
  • std::is_xxx 系列的实现基础

📌 实战用途:

  • 模板选择(启用/禁用特定函数)
  • 编译期报错控制(static_assert)

✅ 三、enable_if 结合 CRTP 实现“类型约束接口”

#include <type_traits>

template<typename T>
class Printable {
public:
    void print() {
        static_assert(std::is_arithmetic<T>::value, "T 必须是数值类型");
        std::cout << "Value = " << value << std::endl;
    }
    T value;
};

Printable<int> a{10};
a.print();  // OK
// Printable<std::string> b{"test"};  // 编译期报错

📌 技术组合说明:

  • std::is_arithmetic<T> 用于类型判断
  • static_assert 编译期断言,提升类型安全

✅ 四、综合设计:CRTP + traits 定义行为接口系统

// 是否支持加法的特征检测

template<typename T, typename = void>
struct has_plus : std::false_type {};

template<typename T>
struct has_plus<T, decltype(void(std::declval<T>() + std::declval<T>()))> : std::true_type {};

// CRTP 接口

template<typename Derived, typename T>
class Addable {
public:
    void try_add() {
        if constexpr (has_plus<T>::value) {
            T result = static_cast<Derived*>(this)->get() + static_cast<Derived*>(this)->get();
            std::cout << "Add result: " << result << std::endl;
        } else {
            std::cout << "Not addable." << std::endl;
        }
    }
};

class MyInt : public Addable<MyInt, int> {
public:
    int get() const { return 10; }
};

class MyVoid : public Addable<MyVoid, void> {
public:
    void get() const {}
};

📌 技术亮点:

  • 通过 void_t + declval 检测表达式是否合法
  • 配合 if constexpr 提供“条件编译行为”
  • 使用 CRTP 让接口行为自动绑定在派生类上

📚 总结回顾

  • CRTP:模板 + 继承,带来静态多态与零成本内联
  • traits:构建类型元信息判断系统的基石
  • enable_if / static_assert / if constexpr:现代 C++ 类型安全的守护者
  • 两者结合是泛型编程与模板策略模式的进阶门槛

下一篇是否继续进入 Day 8:深入 std::functionlambda 表达式与函数对象?或希望将 CRTP + traits 应用于一个完整架构中(如插件系统、策略注入)?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值