乐于分享
好东西不私藏

C++ 模板编程指南

C++ 模板编程指南
深入理解函数模板与类模板的概念、原理及场景应用。
目录

1.模板概述2.函数模板3.类模板4.变量模板、别名模板与模板模板参数5.模板特化6.模板元编程基础7.车企综合案例8.最佳实践与常见陷阱9.总结


1. 模板概述

1.1 什么是模板

模板是C++泛型编程的基础,允许编写与类型无关的通用代码。编译器根据实际使用的类型自动生成具体代码。

           模板定义              │              ▼    ┌─────────────────────┐    │template <typename T>│    │  max(T a, T b);   │    └─────────────────────┘              │    ┌─────────┼─────────┐    │         │         │    ▼         ▼         ▼max<int>  max<float>  max<double>   │         │           │   ▼         ▼           ▼ 具体函数   具体函数    具体函数

1.2 模板的优势

优势
说明
车企应用场景
代码复用
一次编写,多类型使用
通用消息队列、数据缓冲区
类型安全
编译期类型检查
传感器数据处理
高性能
无运行时开销
实时控制系统
灵活性
支持任意类型
多协议适配器

1.3 模板 vs 宏 vs 继承

// ❌ 宏:无类型检查,难以调试#define MAX(a, b) ((a) > (b) ? (a) : (b))// ❌ 继承:运行时多态,有虚表开销class IComparable {    virtualboolgreaterThan(const IComparable&)0;};// ✅ 模板:编译期多态,类型安全,零开销template <typename T>max(T a, T b){    return (a > b) ? a : b;}

2. 函数模板

2.1 基本语法

// 函数模板定义template <typename T>          // 或 template <class T>add(T a, T b) {    return a + b;}// 使用方式int result1 = add<int>(35);      // 显式指定类型double result2 = add(3.142.71);  // 自动推导类型

2.2 多类型参数

// 多类型参数模板template <typename T, typename U>auto multiply(T a, U b) -> decltype(a * b) {    return a * b;}// 车企示例:单位转换template <typename FromUnit, typename ToUnit>double convert(double value) {    return value * FromUnit::factor / ToUnit::factor;}struct Kilometers { static constexpr double factor = 1.0; };struct Miles { static constexpr double factor = 1.60934; };// 使用double miles = convert<Kilometers, Miles>(100.0);  // 100km -> 62.14 miles

2.3 非类型模板参数

// 非类型参数:编译期常量template <typename T, size_t SIZE>class FixedArray {    T data[SIZE];public:    size_tsize()constreturn SIZE; }};// 车企示例:固定大小的CAN帧缓冲区template <size_t FRAME_COUNT>class CanFrameBuffer {    CanFrame frames[FRAME_COUNT];    size_t head = 0;    size_t tail = 0;public:    boolpush(const CanFrame& frame);    boolpop(CanFrame& frame);    staticconstexprsize_tcapacity()return FRAME_COUNT; }};// 使用:编译期确定大小,无动态分配CanFrameBuffer<64> highPriorityBuffer;CanFrameBuffer<256> normalBuffer;

2.4 函数模板实例化原理

源代码阶段:┌───────────────────────────┐│ template <typename T>     ││ T process(T data) { ... } │└───────────────────────────┘编译阶段 - 遇到调用点:process<int>(42);process<float>(3.14f);process<SensorData>(sensor);实例化生成:┌─────────────────┐  ┌─────────────────┐  ┌─────────────────────┐│ int process(    │  │ float process(  │  │ SensorData process( ││   int data)     │  │   float data)   │  │   SensorData data)  ││ { ... }         │  │ { ... }         │  │ { ... }             │└─────────────────┘  └─────────────────┘  └─────────────────────┘

实例化时机

隐式实例化:首次使用时由编译器自动生成显式实例化:使用 template 关键字强制生成

// 显式实例化声明template intadd<int>(intint);template doubleadd<double>(doubledouble);

2.5 函数模板实例

示例1:传感器数据滤波

// 通用滑动平均滤波器template <typename T, size_t WINDOW_SIZE>class MovingAverageFilter {    T window[WINDOW_SIZE];    size_t index = 0;    size_t count = 0;    T sum = T();public:    filter(T newValue){        if (count < WINDOW_SIZE) {            window[count++] = newValue;            sum += newValue;        } else {            sum -= window[index];            sum += newValue;            window[index] = newValue;            index = (index + 1) % WINDOW_SIZE;        }        return sum / static_cast<T>(count);    }};// 应用于不同传感器MovingAverageFilter<float10> temperatureFilter;   // 温度滤波MovingAverageFilter<int32_t5> rpmFilter;          // 转速滤波MovingAverageFilter<double20> gpsFilter;          // GPS滤波

示例2:通用数据范围检查

// 范围检查模板template <typename T>boolisInRange(T value, T min, T max){    return (value >= min) && (value <= max);}// 带回调的范围检查template <typename T, typename Callback>boolcheckRangeWithAction(T value, T min, T max, Callback onOutOfRange){    if (!isInRange(value, min, max)) {        onOutOfRange(value, min, max);        return false;    }    return true;}// 车企应用voidvalidateEngineParams(float rpm, float coolantTemp){    checkRangeWithAction(rpm, 0.0f8000.0f        [](float v, float min, float max) {            LOG_WARN("RPM out of range: %.1f [%.1f, %.1f]", v, min, max);        });    checkRangeWithAction(coolantTemp, -40.0f150.0f,        [](float v, float min, float max) {            triggerOverheatWarning(v);        });}

3. 类模

3.1 基本语法

// 类模板定义template <typename T>class Container {private:    T* data;    size_t size;public:    Container();    ~Container();    voidadd(const T& item);    T& get(size_t index);    size_tgetSize()const;};// 成员函数在类外定义template <typename T>void Container<T>::add(const T& item) {    // 实现...}// 使用Container<int> intContainer;Container<CanMessage> messageContainer;

3.2 类模板实例化原理

类模板定义 (蓝图)       │       ▼┌─────────────────────────────┐│ template <typename T>       ││ class Queue {               ││     T* data;                ││     voidenqueue(const T&); ││     dequeue();            ││ };                          │└─────────────────────────────┘       │       │ 实例化请求       ▼┌───────────────┬────────────────┬──────────────┐│ Queue<int>    │Queue<float>    │Queue<Msg>    ││               │                │              ││ int* data;    │float* data;    │Msg* data;    ││ enqueue(int)  │enqueue(float)  │enqueue(Msg)  ││ dequeue()->intdequeue()->floatdequeue()->Msg│└───────────────┴────────────────┴──────────────┘      独立的类           独立的类        独立的类

关键点

每种类型参数组合生成独立的类只有被调用的成员函数才会被实例化类模板可以有默认参数

3.3 默认模板参数

// 带默认参数的类模板template <typename T, typename Allocator = std::allocator<T>>class DynamicArray {    T* data;    Allocator allocator;    // ...};// 车企示例:可配置的消息队列template <typename MessageType,           size_t CAPACITY = 64,          typename LockPolicy = NoLock>class MessageQueue {    MessageType buffer[CAPACITY];    size_t head = 0;    size_t tail = 0;    LockPolicy lock;public:    boolenqueue(const MessageType& msg){        typename LockPolicy::Guard guard(lock);        // 入队逻辑...    }};// 使用不同配置MessageQueue<CanMessage> defaultQueue;                    // 64容量,无锁MessageQueue<CanMessage, 128> largerQueue;                // 128容量,无锁MessageQueue<CanMessage, 64, SpinLock> threadSafeQueue;   // 64容量,自旋锁

3.4 类模板与继承

// 模板类作为基类template <typename T>class BaseContainer {protected:    T* data;    size_t capacity;public:    virtualvoidadd(const T& item)0;};// 派生类继承模板类template <typename T>class Stack : public BaseContainer<T> {public:    voidadd(const T& item)override/* push实现 */ }    pop();};// 非模板类继承模板类(具体化)class IntStack : public BaseContainer<int> {public:    voidadd(constint& item)override/* 特定实现 */ }};

3.5 车企类模板实例

示例1:通用状态机模板

// 泛型状态机template <typename StateEnum, typename EventEnum>class StateMachine {public:    using StateHandler = void (*)(EventEnum event);    using TransitionGuard = bool (*)();    struct Transition {        StateEnum fromState;        EventEnum event;        StateEnum toState;        TransitionGuard guard;        StateHandler action;    };private:    StateEnum currentState;    std::vector<Transition> transitions;public:    StateMachine(StateEnum initialState) : currentState(initialState) {}    voidaddTransition(const Transition& t){        transitions.push_back(t);    }    boolprocessEvent(EventEnum event){        for (const auto& t : transitions) {            if (t.fromState == currentState && t.event == event) {                if (t.guard == nullptr || t.guard()) {                    if (t.action) t.action(event);                    currentState = t.toState;                    return true;                }            }        }        return false;    }    StateEnum getState()constreturn currentState; }};// 车企应用:发动机状态机enum class EngineState { OFF, CRANKING, IDLE, RUNNING, FAULT };enum class EngineEvent { START, CRANK_COMPLETE, ACCELERATE, STOP, ERROR };StateMachine<EngineState, EngineEvent> engineFSM(EngineState::OFF);// 配置转换engineFSM.addTransition({EngineState::OFF, EngineEvent::START,                          EngineState::CRANKING, nullptr, onStartCranking});engineFSM.addTransition({EngineState::CRANKING, EngineEvent::CRANK_COMPLETE,                         EngineState::IDLE, nullptr, onIdleReached});

示例2:环形缓冲区模板

// 线程安全的环形缓冲区template <typename T, size_t CAPACITY>class RingBuffer {    T buffer[CAPACITY];    volatile size_t head = 0;    volatile size_t tail = 0;public:    boolpush(const T& item){        size_t nextHead = (head + 1) % CAPACITY;        if (nextHead == tail) {            return false;  // 满        }        buffer[head] = item;        head = nextHead;        return true;    }    boolpop(T& item){        if (head == tail) {            return false;  // 空        }        item = buffer[tail];        tail = (tail + 1) % CAPACITY;        return true;    }    boolisEmpty()constreturn head == tail; }    boolisFull()constreturn ((head + 1) % CAPACITY) == tail; }    size_tsize()constreturn (head - tail + CAPACITY) % CAPACITY; }    staticconstexprsize_tcapacity()return CAPACITY - 1; }};// 车企应用RingBuffer<CanFrame, 128> canRxBuffer;      // CAN接收缓冲RingBuffer<DiagRequest, 32> diagBuffer;     // 诊断请求缓冲RingBuffer<SensorSample, 256> sensorBuffer; // 传感器数据缓冲

示例3:通用协议解析器

// 协议帧解析器模板template <typename FrameType, typename PayloadType>class ProtocolParser {public:    using FrameHandler = std::function<void(const PayloadType&)>;private:    std::map<uint32_t, FrameHandler> handlers;public:    voidregisterHandler(uint32_t frameId, FrameHandler handler){        handlers[frameId] = handler;    }    boolparse(const FrameType& frame){        auto it = handlers.find(frame.getId());        if (it != handlers.end()) {            PayloadType payload;            if (decode(frame, payload)) {                it->second(payload);                return true;            }        }        return false;    }protected:    virtualbooldecode(const FrameType& frame, PayloadType& payload)0;};// CAN协议实现struct CanFrame { uint32_t id; uint8_t data[8]; uint8_t dlc; };struct EngineData { float rpm; float coolantTemp; };class CanEngineParser : public ProtocolParser<CanFrame, EngineData> {protected:    booldecode(const CanFrame& frame, EngineData& data)override{        // 解析CAN帧数据        data.rpm = (frame.data[0] << 8 | frame.data[1]) * 0.25f;        data.coolantTemp = frame.data[2] - 40.0f;        return true;    }};

4. 变量模板、别名模板与模板模板参数

4.1 变量模板 (C++14)

变量模板允许定义参数化的变量,在编译期根据类型生成不同的常量值。

4.1.1 基本语法

// 变量模板定义template <typename T>constexpr T pi = T(3.14159265358979323846);// 使用float pi_f = pi<float>;     // 3.14159fdouble pi_d = pi<double>;   // 3.14159265358979long double pi_ld = pi<long double>;

4.1.2 带非类型参数的变量模板

// 编译期数组大小template <size_t N>constexpr size_t arraySize = N;// 编译期位掩码template <unsigned Bit>constexpr uint32_t bitMask = 1u << Bit;// 使用uint32_t mask = bitMask<3>;  // 0x08uint32_t clearBit3 = value & ~bitMask<3>;

4.1.3 车企应用:类型相关常量

// 不同数据类型的有效范围template <typename T>constexpr T sensorMin = T();template <typename T>constexpr T sensorMax = T();// 特化:温度传感器范围template <>constexpr float sensorMin<float> = -40.0f;template <>constexpr float sensorMax<float> = 150.0f;// 特化:转速范围template <>constexpr uint16_t sensorMin<uint16_t> = 0;template <>constexpr uint16_t sensorMax<uint16_t> = 8000;// 通用范围检查template <typename T>boolisValidSensorValue(T value){    return value >= sensorMin<T> && value <= sensorMax<T>;}// 使用bool validTemp = isValidSensorValue(85.5f);     // 检查温度bool validRpm = isValidSensorValue<uint16_t>(3500);  // 检查转速

4.1.4 类型萃取变量模板

// 标准库风格的类型萃取(C++17简化)template <typename T>constexpr bool is_pointer_v = std::is_pointer<T>::value;template <typename T>constexpr bool is_integral_v = std::is_integral<T>::value;template <typename T, typename U>constexpr bool is_same_v = std::is_same<T, U>::value;// 应用:协议字节序template <typename T>constexpr bool needs_byte_swap = (sizeof(T) > 1) && !std::is_same_v<T, float>;// CAN数据解析时使用template <typename T>parseCanData(constuint8_t* data){    T value;    std::memcpy(&value, data, sizeof(T));    ifconstexpr(needs_byte_swap<T>){        value = byteSwap(value);  // 大小端转换    }    return value;}

4.2 别名模板 (C++11)

别名模板使用 using 关键字创建模板化的类型别名,比 typedef 更强大和灵活。

4.2.1 基本语法

// 传统typedef(不支持模板)typedef std::vector<int> IntVector;  // 只能用于具体类型// 别名模板(支持参数化)template <typename T>using Vector = std::vector<T>;template <typename T>using Ptr = T*;template <typename T>using ConstRef = const T&;// 使用Vector<int> intVec;           // std::vector<int>Vector<CanFrame> frameVec;    // std::vector<CanFrame>Ptr<float> floatPtr;          // float*ConstRef<std::string> strRef; // const std::string&

4.2.2 简化复杂类型

// 简化嵌套模板template <typename Key, typename Value>using HashMap = std::unordered_map<Key, Value>;template <typename T>using SharedPtr = std::shared_ptr<T>;template <typename T>using UniquePtr = std::unique_ptr<T>;// 函数指针别名template <typename Ret, typename... Args>using FuncPtr = Ret(*)(Args...);// 回调函数别名template <typename T>using Callback = std::function<void(const T&)>;// 使用HashMap<uint32_t, std::string> errorCodeMap;Callback<SensorData> onSensorUpdate;

4.2.3 车企应用:消息处理器别名

// 消息处理函数类型template <typename MessageType>using MessageHandler = std::function<void(const MessageType&)>;template <typename MessageType>using MessageValidator = std::function<bool(const MessageType&)>;// 消息队列别名template <typename T, size_t N = 64>using MessageQueue = RingBuffer<T, N>;// CAN消息相关别名using CanHandler = MessageHandler<CanFrame>;using CanValidator = MessageValidator<CanFrame>;using CanQueue = MessageQueue<CanFrame, 128>;// 诊断消息相关别名using DiagHandler = MessageHandler<DiagRequest>;using DiagQueue = MessageQueue<DiagRequest, 32>;// 注册表类型template <typename IdType, typename HandlerType>using HandlerRegistry = std::map<IdType, HandlerType>;using CanHandlerRegistry = HandlerRegistry<uint32_t, CanHandler>;// 使用CanHandlerRegistry canHandlers;canHandlers[0x100] = [](const CanFrame& f) { processEngineData(f); };canHandlers[0x200] = [](const CanFrame& f) { processBatteryData(f); };

4.2.4 提取嵌套类型

// 提取容器元素类型template <typename Container>using ValueType = typename Container::value_type;template <typename Container>using Iterator = typename Container::iterator;// 提取函数返回类型template <typename Func>using ReturnType = typename std::invoke_result<Func>::type;// 车企应用:状态机类型萃取template <typename FSM>using StateType = typename FSM::state_type;template <typename FSM>using EventType = typename FSM::event_type;// 通用状态机日志template <typename FSM>voidlogTransition(const FSM& fsm, EventType<FSM> event){    LOG_INFO("FSM transition: event=%d, state=%d"             static_cast<int>(event),             static_cast<int>(fsm.getState()));}

4.3 模板模板参数

模板模板参数允许将模板本身作为参数传递,实现更高层次的抽象。

4.3.1 基本语法

// 模板模板参数声明template <template <typenameclass Containertypename T>class Wrapper {    Container<T> data;  // 使用传入的容器模板public:    voidadd(const T& item){ data.push_back(item); }};// 使用Wrapper<std::vector, int> vecWrapper;      // 使用vectorWrapper<std::list, int> listWrapper;       // 使用listWrapper<std::deque, std::string> dequeWrapper;

4.3.2 带多个参数的模板模板参数

// 容器通常有多个模板参数(类型+分配器)template <template <typenametypenameclass Container          typename T,          typename Allocator = std::allocator<T>>class FlexibleStorage {    Container<T, Allocator> storage;public:    voidstore(const T& item){ storage.push_back(item); }    size_tcount()constreturn storage.size(); }};// 使用FlexibleStorage<std::vector, int> vecStorage;FlexibleStorage<std::deque, CanFrame> canStorage;

4.3.3 车企应用:可配置的消息系统

// 消息系统框架 - 容器策略可配置template <typename MessageType,          template <typenamesize_tclass QueuePolicy,          size_t QueueSize = 64>class MessageSystem {    QueuePolicy<MessageType, QueueSize> rxQueue;    QueuePolicy<MessageType, QueueSize> txQueue;public:    boolsend(const MessageType& msg){        return txQueue.push(msg);    }    boolreceive(MessageType& msg){        return rxQueue.pop(msg);    }    size_tpendingRx()constreturn rxQueue.size(); }    size_tpendingTx()constreturn txQueue.size(); }};// 不同的队列实现template <typename T, size_t N>class RingBuffer { /* 环形缓冲区实现 */ };template <typename T, size_t N>class PriorityQueue { /* 优先级队列实现 */ };template <typename T, size_t N>class LockFreeQueue { /* 无锁队列实现 */ };// 根据需求选择不同队列策略MessageSystem<CanFrame, RingBuffer, 128> normalCanSystem;MessageSystem<DiagRequest, PriorityQueue, 32> diagSystem;MessageSystem<SafetyMsg, LockFreeQueue, 64> safetySystem;

4.3.4 车企应用:通用数据记录器

// 日志存储策略template <typename T, size_t N>class CircularLog {    T entries[N];    size_t index = 0;public:    voidlog(const T& entry){        entries[index] = entry;        index = (index + 1) % N;    }    // 获取最近N条记录...};template <typename T, size_t N>class SequentialLog {    std::vector<T> entries;public:    voidlog(const T& entry){        if (entries.size() < N) {            entries.push_back(entry);        }    }};// 通用数据记录器template <typename DataType,          template <typenamesize_tclass StoragePolicy,          size_t Capacity = 1000>class DataLogger {    StoragePolicy<DataType, Capacity> storage;public:    voidrecord(const DataType& data){        // 添加时间戳等元数据        storage.log(data);    }};// 车辆数据记录配置struct DriveEvent { uint64_t time; float speed; float rpm; };struct FaultRecord { uint32_t dtc; uint64_t time; uint8_t severity; };// 循环日志 - 持续覆盖旧数据DataLogger<DriveEvent, CircularLog, 10000> driveLogger;// 顺序日志 - 保留首次N条故障DataLogger<FaultRecord, SequentialLog, 500> faultLogger;

4.3.5 车企应用:协议适配器工厂

// 协议解析器模板template <typename FrameType>class IProtocolParser {public:    virtualboolparse(const FrameType& frame)0;    virtual ~IProtocolParser() = default;};// 协议适配器工厂template <typename FrameType,          template <typenameclass ParserType>class ProtocolAdapterFactory {public:    static std::unique_ptr<IProtocolParser<FrameType>> create() {        return std::make_unique<ParserType<FrameType>>();    }};// 不同协议解析器template <typename Frame>class J1939Parser : public IProtocolParser<Frame> {public:    boolparse(const Frame& frame)override{        // J1939协议解析        return true;    }};template <typename Frame>class UdsParser : public IProtocolParser<Frame> {public:    boolparse(const Frame& frame)override{        // UDS协议解析        return true;    }};// 使用工厂创建解析器auto j1939 = ProtocolAdapterFactory<CanFrame, J1939Parser>::create();auto uds = ProtocolAdapterFactory<CanFrame, UdsParser>::create();

4.4 三种模板对比总结

特性
变量模板
别名模板
模板模板参数
引入版本
C++14
C++11
C++98
用途
参数化常量
简化类型名
传递模板本身
语法
template<T> constexpr T vtemplate<T> using Alias = ...template<template<T> class C>
实例化结果
变量
类型别名
模板实例
典型场景
类型相关常量、配置值
简化嵌套类型、回调类型
容器策略、工厂模式

5. 模板特化

模板特化是指:在保留主模板通用能力的前提下,针对某些特定类型特定参数组合提供更合适的实现。

主模板负责“覆盖大多数情况”,特化版本负责“处理少数特殊情况”。这和业务代码里的“默认流程 + 特例流程”很像。

              主模板                                     处理大多数类型                      ┌──────────────────────┐     Template<T>              └──────────────────────┘                                             遇到特殊类型时                                    ┌──────────────────────┐               Template<std::string>              └──────────────────────┘                     部分参数满足条件时              ┌──────────────────────┐     Template<TT>           └──────────────────────┘

5.1 为什么需要模板特化

当主模板的默认实现对某些类型不成立,或者虽然能工作但语义不准确、性能不理想时,就需要特化。

典型场景:

某些类型的处理逻辑完全不同,例如 std::string 需要加引号序列化。某类参数组合存在更高效的实现,例如指针类型、相同类型组合。需要为类型萃取、策略选择提供编译期分支能力。需要对特殊对象增加额外校验,例如通信帧、硬件句柄、浮点数据。

可以把模板特化理解成“编译期 if-else”,区别在于它不是运行时判断,而是编译器在实例化模板时直接选择最匹配的版本。

5.2 特化的分类

类型
说明
是否常见
全特化
把模板参数全部确定下来,为某一个具体类型/组合写专门实现
很常见
偏特化
只固定一部分模板参数,其余参数仍保持泛型
常见于类模板

需要注意:

类模板支持全特化和偏特化。函数模板支持全特化,但不支持偏特化对函数模板来说,如果只是想针对某类参数提供更合适的版本,很多时候函数重载比特化更直接。

5.3 全特化

为特定类型提供完全不同的实现:

// 主模板template <typename T>class Serializer {public:    static std::string serialize(const T& obj){        // 通用序列化实现        return std::to_string(obj);    }};// 全特化:std::stringtemplate <>class Serializer<std::string> {public:    static std::string serialize(const std::string& obj){        return "\"" + obj + "\"";  // 字符串加引号    }};// 全特化:CanFrametemplate <>class Serializer<CanFrame> {public:    static std::string serialize(const CanFrame& frame){        char buf[64];        snprintf(buf, sizeof(buf), "ID:0x%03X DLC:%d", frame.id, frame.dlc);        return std::string(buf);    }};

5.4 偏特化

对部分参数进行特化:

// 主模板template <typename T, typename U>classPair{    T first;    U second;};// 偏特化:当两个类型相同时template <typename T>classPair<TT{    T data[2];public:    T& first() { return data[0]; }    T& second() { return data[1]; }};// 偏特化:第二个参数是指针时template <typename T, typename U>classPair<TU*> {    T first;    U* second;public:    ~Pair() { delete second; }  // 自动管理指针};

5.5 车企特化实例

// 通用数据验证器template <typename T>class DataValidator {public:    staticboolvalidate(const T& data){        // 默认:非零即有效        return data != T();    }};// 特化:浮点数(检查NaN和范围)template <>class DataValidator<float> {public:    staticboolvalidate(float data){        return !std::isnan(data) && !std::isinf(data);    }    staticboolvalidateRange(float data, float min, float max){        return validate(data) && data >= min && data <= max;    }};// 特化:CAN帧template <>class DataValidator<CanFrame> {public:    staticboolvalidate(const CanFrame& frame){        // 标准帧ID范围检查        if (frame.id > 0x7FFreturn false;        // DLC检查        if (frame.dlc > 8return false;        return true;    }};// 偏特化:指针类型template <typename T>class DataValidator<T*> {public:    staticboolvalidate(T* ptr){        return ptr != nullptr && DataValidator<T>::validate(*ptr);    }};

6. 模板元编程基础

模板元编程(Template Metaprogramming, TMP)可以理解为:把模板本身当作一种“编译期语言”来使用。程序员并不是只用模板生成不同类型的函数或类,还可以借助模板参数、特化、递归定义和类型推导,在编译阶段完成计算、类型判断和代码选择

它和普通模板的区别在于:

维度
普通模板
模板元编程
主要目标
代码复用
编译期计算与编译期分派
处理对象
函数、类的泛型化
类型、常量、表达式规则
执行时机
模板实例化时生成代码
模板实例化过程中完成推导
常见结果
Vector<int>
max<double>
Factorial<5>::value
IsPointer<T>::value

从本质上说,模板元编程做了三类事情:

1.值计算:在编译期求出某个常量结果,例如阶乘、数组大小、对齐值。2.类型计算:根据输入类型生成新类型,例如移除 const、提取底层类型。3.条件选择:根据类型特征决定某段代码是否参与重载决议或实例化。

一个典型的思维方式如下:

输入类型/常量    │    ▼模板匹配与特化    │    ▼递归展开 / 条件筛选    │    ▼生成结果:值、类型或可用接口

模板元编程的价值主要体现在以下场景:

零运行时开销:很多判断和计算提前到编译期,运行时无需再做分支。增强类型安全:不满足条件的类型在编译阶段就会被拒绝。构建通用库:标准库中的很多能力,例如类型萃取、迭代器适配,本质上都依赖TMP思想。适配高性能系统:在嵌入式、通信、控制软件中,可以把部分规则固化为编译期约束。

不过,TMP也有明显代价:可读性下降、编译错误信息复杂、编译时间增加。因此工程实践里通常遵循一个原则:优先把模板元编程用于“约束接口”和“消除重复规则”,而不是炫技式地把所有逻辑都塞到模板里

下面从编译期计算、类型萃取以及 SFINAE 三个最基础的角度入门。

6.1 编译期计算

// 编译期阶乘template <unsigned N>struct Factorial {    static constexpr unsigned value = N * Factorial<N - 1>::value;};template <>struct Factorial<0> {    static constexpr unsigned value = 1;};// 使用constexpr unsigned fact5 = Factorial<5>::value;  // 120,编译期确定

6.2 类型萃取

// 判断是否为指针类型template <typename T>struct IsPointer {    static constexpr bool value = false;};template <typename T>struct IsPointer<T*> {    static constexpr bool value = true;};// 移除const修饰template <typename T>struct RemoveConst {    using type = T;};template <typename T>struct RemoveConst<const T> {    using type = T;};// 车企应用:根据类型选择处理方式template <typename T>voidprocess(T data){    ifconstexpr(IsPointer<T>::value){        // 指针类型处理        if (data != nullptr) {            processValue(*data);        }    } else {        // 值类型处理        processValue(data);    }}

6.3 SFINAE 与 enable_if

// 仅对整数类型启用template <typename T>typename std::enable_if<std::is_integral<T>::value, T>::typesafeDivide(T a, T b) {    if (b == 0return 0;    return a / b;}// 仅对浮点类型启用template <typename T>typename std::enable_if<std::is_floating_point<T>::value, T>::typesafeDivide(T a, T b) {    if (std::abs(b) < 1e-10return 0;    return a / b;}// 车企示例:类型安全的信号处理template <typename T,          typename = std::enable_if_t<std::is_arithmetic<T>::value>>class SignalProcessor {    T currentValue;    T minValue;    T maxValue;public:    voidupdate(T newValue){        currentValue = std::clamp(newValue, minValue, maxValue);    }};

7. 车企综合案例

7.1 案例:通用诊断服务框架

// 诊断服务接口模板template <typename RequestType, typename ResponseType>class IDiagnosticService {public:    virtual ~IDiagnosticService() = default;    virtualuint8_tgetServiceId()const0;    virtualboolhandleRequest(const RequestType& req, ResponseType& resp)0;};// 诊断服务管理器template <typename RequestType, typename ResponseType>class DiagnosticServiceManager {    std::map<uint8_t, std::unique_ptr<IDiagnosticService<RequestType, ResponseType>>> services;public:    voidregisterService(std::unique_ptr<IDiagnosticService<RequestType, ResponseType>> svc){        services[svc->getServiceId()] = std::move(svc);    }    booldispatch(const RequestType& req, ResponseType& resp){        auto it = services.find(req.serviceId);        if (it != services.end()) {            return it->second->handleRequest(req, resp);        }        return false;    }};// 具体诊断请求/响应类型struct UdsRequest {    uint8_t serviceId;    std::vector<uint8_t> data;};struct UdsResponse {    uint8_t serviceId;    bool positive;    std::vector<uint8_t> data;};// 具体服务实现class ReadDataByIdService : public IDiagnosticService<UdsRequest, UdsResponse> {public:    uint8_tgetServiceId()constoverridereturn 0x22; }    boolhandleRequest(const UdsRequest& req, UdsResponse& resp)override{        resp.serviceId = 0x62;        resp.positive = true;        // 读取数据逻辑...        return true;    }};

7.2 案例:多协议通信适配器

// 通信接口模板template <typename FrameType>class ICommunicationChannel {public:    virtual ~ICommunicationChannel() = default;    virtualboolsend(const FrameType& frame)0;    virtualboolreceive(FrameType& frame, uint32_t timeoutMs)0;    virtualboolisConnected()const0;};// CAN通道实现class CanChannel : public ICommunicationChannel<CanFrame> {    int fd;public:    boolsend(const CanFrame& frame)override{        // CAN发送实现    }    boolreceive(CanFrame& frame, uint32_t timeoutMs)override{        // CAN接收实现    }    boolisConnected()constoverridereturn fd >= 0; }};// 以太网通道实现struct EthFrame { uint8_t data[1500]; size_t len; };class EthernetChannel : public ICommunicationChannel<EthFrame> {    int socket;public:    boolsend(const EthFrame& frame)override/* 实现 */ }    boolreceive(EthFrame& frame, uint32_t timeoutMs)override/* 实现 */ }    boolisConnected()constoverridereturn socket >= 0; }};// 通用消息收发器template <typename ChannelType, typename FrameType>class MessageTransceiver {    std::unique_ptr<ICommunicationChannel<FrameType>> channel;    RingBuffer<FrameType, 64> txQueue;    RingBuffer<FrameType, 128> rxQueue;public:    voidsetChannel(std::unique_ptr<ICommunicationChannel<FrameType>> ch){        channel = std::move(ch);    }    boolsendAsync(const FrameType& frame){        return txQueue.push(frame);    }    voidprocessTx(){        FrameType frame;        while (txQueue.pop(frame)) {            channel->send(frame);        }    }};

7.3 案例:类型安全的配置系统

// 配置项模板template <typename T, uint32_t ID>class ConfigItem {    T value;    T defaultValue;    T minValue;    T maxValue;    bool modified = false;public:    static constexpr uint32_t id = ID;    ConfigItem(T def, T min, T max)        : value(def), defaultValue(def), minValue(min), maxValue(max) {}    boolset(T newValue){        if (newValue < minValue || newValue > maxValue) return false;        value = newValue;        modified = true;        return true;    }    get()constreturn value; }    voidreset(){ value = defaultValue; modified = false; }    boolisModified()constreturn modified; }};// 车企配置定义namespace VehicleConfig {    // 配置ID定义    enum ConfigId : uint32_t {        ENGINE_IDLE_RPM = 0x1001,        MAX_VEHICLE_SPEED = 0x1002,        WARNING_COOLANT_TEMP = 0x1003    };    // 类型安全的配置项    ConfigItem<uint16_t, ENGINE_IDLE_RPM> idleRpm(8006001200);    ConfigItem<uint8_t, MAX_VEHICLE_SPEED> maxSpeed(180100250);    ConfigItem<int8_t, WARNING_COOLANT_TEMP> warnTemp(10590120);}// 使用voidapplyConfig(){    VehicleConfig::idleRpm.set(850);    uint16_t rpm = VehicleConfig::idleRpm.get();}

8. 最佳实践与常见陷阱

8.1 最佳实践

实践
说明
头文件中定义
模板定义放在 .h 或 .hpp 文件中
使用 typename
依赖名使用 typename 声明为类型
提供清晰接口
使用有意义的模板参数名
限制实例化
使用显式实例化减少编译时间
SFINAE约束
使用 enable_if 限制模板适用类型

8.2 常见陷阱

// ❌ 陷阱1:模板定义放在.cpp文件// template.htemplate <typename T>class MyClass {    voidmethod();  // 声明};// template.cpp - 错误!链接时找不到template <typename T>void MyClass<T>::method() { }// ✅ 正确:定义也放在头文件// ❌ 陷阱2:忘记typenametemplate <typename T>voidfunc(){    T::value_type x;           // 错误    typename T::value_type x;  // 正确}// ❌ 陷阱3:代码膨胀// 过多实例化导致二进制体积增大// 解决:使用显式实例化、提取公共基类// ❌ 陷阱4:依赖名查找问题template <typename T>class Derived : public Base<T> {    voidmethod(){        value = 10;      // 错误:找不到value        this->value = 10// 正确:明确访问基类成员    }};

8.3 编译时间优化

// 方法1:显式实例化(减少重复实例化)// config_types.cpp#include "ConfigItem.hpp"template classConfigItem<int0>;template classConfigItem<float0>;template classConfigItem<uint32_t0>;// 方法2:外部模板声明// other.cppextern template classConfigItem<int0>;  // 不在此编译单元实例化

9. 总结

概念
函数模板
类模板
目的
创建通用函数
创建通用类
实例化
调用时自动/显式
声明对象时
特化
支持全特化
支持全特化+偏特化
常见用途
算法、工具函数
容器、策略类、适配器

车企应用总结

实时系统:使用固定大小模板避免动态分配协议适配:类模板实现多协议统一接口状态管理:泛型状态机适配不同业务域数据验证:模板特化处理不同数据类型配置系统:类型安全的编译期配置


参考资源

1.《C++ Templates: The Complete Guide》(2nd Edition)2.《Effective Modern C++》- Scott Meyers3.AUTOSAR C++14 Coding Guidelines4.《C++ Primer》(5th Edition) - Template章节


基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-04-19 23:27:32 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/531237.html
  2. 运行时间 : 0.115017s [ 吞吐率:8.69req/s ] 内存消耗:4,975.78kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=75c9e6cf39a04203ff1de0e8dba6fd8a
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.80 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000818s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000816s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.003108s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000295s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000486s ]
  6. SELECT * FROM `set` [ RunTime:0.000197s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000494s ]
  8. SELECT * FROM `article` WHERE `id` = 531237 LIMIT 1 [ RunTime:0.004762s ]
  9. UPDATE `article` SET `lasttime` = 1776612453 WHERE `id` = 531237 [ RunTime:0.003011s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000242s ]
  11. SELECT * FROM `article` WHERE `id` < 531237 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000460s ]
  12. SELECT * FROM `article` WHERE `id` > 531237 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.005822s ]
  13. SELECT * FROM `article` WHERE `id` < 531237 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.001177s ]
  14. SELECT * FROM `article` WHERE `id` < 531237 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000748s ]
  15. SELECT * FROM `article` WHERE `id` < 531237 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.006944s ]
0.118190s