C++模板进阶技巧全解析

  1. 模板特化

模板特化允许为特定类型提供定制化的实现。

  • 全特化:为所有模板参数指定具体类型。
cpp 复制代码
template <typename T>
class MyClass {
public:
    void print() { std::[](https://en.cppreference.com/w/cpp/io/c) << "Generic type\n"; }
};

// 全特化版本
template <>
class MyClass<int> {
public:
    void print() { std::[](https://en.cppreference.com/w/cpp/io/c) << "Specialized for int\n"; }
};
  • 偏特化:为部分模板参数指定类型或约束。
cpp 复制代码
template <typename T1, typename T2>
class MyPair { /*...*/ };

// 偏特化:当两个类型相同时
template <typename T>
class MyPair<T, T> { /*...*/ };

2. 可变参数模板

允许模板接受任意数量的参数,使用...语法。

cpp 复制代码
template <typename... Args>
void printAll(Args... args) {
    (std::[](https://en.cppreference.com/w/cpp/io/c) << ... << args) << '\n'; // 折叠表达式(C++17)
}

// 递归展开示例
template <typename T>
void print(T t) {
    std::[](https://en.cppreference.com/w/cpp/io/c) << t << ' ';
}

template <typename T, typename... Args>
void print(T t, Args... args) {
    print(t);
    print(args...); // 递归调用
}

3. 模板元编程

在编译期执行计算,利用模板实例化机制。

cpp 复制代码
// 编译期计算阶乘
template <int N>
struct Factorial {
    static const int value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0> {
    static const int value = 1;
};

// 使用
int main() {
    std::[](https://en.cppreference.com/w/cpp/io/c) << Factorial<5>::value; // 输出120
}

4. SFINAE

"替换失败不是错误",用于约束模板的有效性。

cpp 复制代码
#include <type_traits>

template <typename T>
auto foo(T t) -> std::enable_if_t<std::is_integral_v<T>, void> {
    std::[](https://en.cppreference.com/w/cpp/io/c) << "Integral type\n";
}

template <typename T>
auto foo(T t) -> std::enable_if_t<!std::is_integral_v<T>, void> {
    std::[](https://en.cppreference.com/w/cpp/io/c) << "Non-integral type\n";
}

5. 概念约束 (C++20)

使用conceptrequires明确模板参数要求。

cpp 复制代码
template <typename T>
concept Addable = requires(T a, T b) {
    { a + b } -> std::convertible_to<T>;
};

template <Addable T>
T add(T a, T b) {
    return a + b;
}

6. 模板与完美转发

结合万能引用std::forward实现参数高效传递。

cpp 复制代码
template <typename... Args>
void wrapper(Args&&... args) {
    target(std::forward<Args>(args)...);
}

注意事项

  1. 模板错误信息通常冗长复杂,需耐心分析
  2. 避免过度使用模板元编程导致编译时间过长
  3. 明确typenametemplate在依赖类型中的使用场景
相关推荐
侠客行03178 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
蛇皮划水怪8 小时前
深入浅出LangChain4J
java·langchain·llm
灰子学技术9 小时前
go response.Body.close()导致连接异常处理
开发语言·后端·golang
老毛肚9 小时前
MyBatis体系结构与工作原理 上篇
java·mybatis
风流倜傥唐伯虎10 小时前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
二十雨辰10 小时前
[python]-AI大模型
开发语言·人工智能·python
Yvonne爱编码10 小时前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
Re.不晚10 小时前
JAVA进阶之路——无奖问答挑战1
java·开发语言
你这个代码我看不懂10 小时前
@ConditionalOnProperty不直接使用松绑定规则
java·开发语言
pas13610 小时前
41-parse的实现原理&有限状态机
开发语言·前端·javascript