乐于分享
好东西不私藏

模板元编程没那么可怕,这几个技巧够你应付90%的场景

模板元编程没那么可怕,这几个技巧够你应付90%的场景

模板元编程没那么可怕,这几个技巧够你应付90%的场景

C++哪些有用的冷特性(四) · Dr.Guo's Blog · 2026-04-26


目录

  1. 1. 这篇讲什么
  2. 2. 模板元编程是什么?一句话讲清楚
  3. 3. 技巧一:类型萃取(Type Traits)——编译期的"类型开关"
  4. 4. 技巧二:SFINAE——让编译器帮你选函数
  5. 5. 技巧三:if constexpr——SFINAE 的现代替代品
  6. 6. 技巧四:变参模板(Variadic Templates)——参数包展开
  7. 7. 技巧五:模板递归——编译期的循环
  8. 8. 技巧六:CRTP——静态多态,零开销继承
  9. 9. 技巧七:标签分发(Tag Dispatch)——编译期的策略模式
  10. 10. 实战:一个通用的 to_string 实现
  11. 11. 实战:编译期类型列表操作
  12. 12. 总结:模板元编程工具箱

一、这篇讲什么

模板元编程(Template Metaprogramming,TMP)在 C++ 社区里名声不太好——"黑魔法"、"代码像天书"、"只有编译器能看懂"。

但现实是:你不需要成为模板大师,掌握几个核心技巧就能应付 90% 的场景。而且 C++14/17/20 的改进让模板代码的可读性大幅提升——if constexpr 直接干掉了大量 SFINAE 滥用,auto 参数让模板签名简洁了很多。

这篇不讲理论,直接给你 7 个实用技巧 + 2 个实战,看完就能用。


二、模板元编程是什么?一句话讲清楚

模板元编程 = 用模板在编译期做类型计算和代码生成。

普通编程操作的是(变量、数据),模板元编程操作的是类型。编译器就是你的"运行时",模板实例化就是"执行"。

// 普通编程:操作值int x = 10;int y = x + 20;  // 运行时计算// 模板元编程:操作类型template<typename T>struct TypeSize {    static constexpr size_t value = sizeof(T);  // 编译期计算};// 编译期"调用"static_assert(TypeSize<int>::value == 4);static_assert(TypeSize<double>::value == 8);

就这么简单。所有模板元编程的本质都是这个模式——用类型作为参数,在编译期生成代码或计算值


三、技巧一:类型萃取(Type Traits)——编译期的"类型开关"

<type_traits> 是 C++11 引入的,提供了一整套编译期类型判断和转换工具。这是模板元编程的基石。

判断类型特征

#include <type_traits>static_assert(std::is_integral<int>::value);           // truestatic_assert(std::is_integral<bool>::value);           // truestatic_assert(!std::is_integral<float>::value);         // falsestatic_assert(std::is_pointer<int*>::value);            // truestatic_assert(std::is_array<int[10]>::value);           // truestatic_assert(std::is_const<const int>::value);         // truestatic_assert(std::is_same<int, int>::value);           // truestatic_assert(!std::is_same<int, unsigned int>::value); // false

条件类型选择

#include <type_traits>// 根据条件选择类型using IntType = std::conditional<sizeof(int) == 4, int32_t, int64_t>::type;// 移除/添加修饰符using CleanInt = std::remove_const<const int>::type;     // intusing AddConst = std::add_const<int>::type;               // const intusing DecayType = std::decay<int&&>::type;                // int// 获取公共类型using Common = std::common_type<int, double>::type;       // double

实战:安全的类型转换函数

#include <type_traits>#include <iostream>#include <string>// 只对算术类型做数值转换,其他类型编译报错template<typename To, typename From>typename std::enable_if<std::is_arithmetic<From>::value &&                         std::is_arithmetic<To>::value, To>::typesafe_convert(From val){    // 检查是否会丢失精度if constexpr (std::is_floating_point<To>::value){        return static_cast<To>(val);    } else {        if (static_cast<double>(val) > static_cast<double>(std::numeric_limits<To>::max())) {            throw std::overflow_error("safe_convert: value too large");        }        return static_cast<To>(val);    }}int main(){    auto a = safe_convert<double>(42);    // OK: 42.0    auto b = safe_convert<int>(3.14);     // OK: 3    // auto c = safe_convert<int>("hello"); // 编译错误:不是算术类型    std::cout << a << ", " << b << std::endl;    return 0;}

常用 type_traits 速查:

分类
常用 trait
说明
类型判断
is_integral
is_floating_pointis_pointeris_arrayis_classis_enumis_function
判断类型属性
类型关系
is_same
is_base_ofis_convertible
判断类型间关系
类型修改
remove_const
remove_referenceadd_pointerdecayconditional
修改/选择类型
函数特征
is_invocable
invoke_resultis_nothrow_invocable
C++17,判断可调用性
属性查询
alignment_of
rankextentunderlying_type
查询类型属性值

四、技巧二:SFINAE——让编译器帮你选函数

SFINAE(Substitution Failure Is Not An Error)是模板元编程的核心机制。简单说:

当模板参数替换失败时,编译器不会报错,而是忽略这个候选函数,继续找其他匹配。

基本原理

#include <iostream>#include <type_traits>// 只有当 T 是整数类型时,这个函数才参与重载决议template<typename T>typename std::enable_if<std::is_integral<T>::value, std::string>::typedescribe(T val){    return "整数类型: " + std::to_string(val);}// 只有当 T 是浮点类型时,这个函数才参与重载决议template<typename T>typename std::enable_if<std::is_floating_point<T>::value, std::string>::typedescribe(T val){    return "浮点类型: " + std::to_string(val);}int main(){    std::cout << describe(42) << std::endl;    // 调用第一个    std::cout << describe(3.14) << std::endl;  // 调用第二个    // describe("hello");  // 编译错误:没有匹配的重载    return 0;}

编译器看到 describe(42) 时:

  1. 1. 尝试第一个模板,T = intis_integral<int> 为 true → 匹配成功
  2. 2. 尝试第二个模板,T = intis_floating_point<int> 为 false → 替换失败,不是错误,忽略
  3. 3. 只剩第一个候选 → 调用它

更简洁的写法:std::void_t

C++17 的 std::void_t 让 SFINAE 检测成员是否存在变得非常简洁:

#include <type_traits>#include <iostream>// 检测类型 T 是否有 size() 方法template<typename T, typename = void>struct has_size : std::false_type {};template<typename T>struct has_size<T, std::void_t<decltype(std::declval<T>().size())>>     : std::true_type {};// 检测类型 T 是否有 begin() 和 end()template<typename T, typename = void>struct is_iterable : std::false_type {};template<typename T>struct is_iterable<T, std::void_t<    decltype(std::declval<T>().begin()),    decltype(std::declval<T>().end())>> : std::true_type {};// 使用struct WithSize {size_t size() const{ return 0; } };struct NoSize { int x; };static_assert(has_size<WithSize>::value);static_assert(!has_size<NoSize>::value);static_assert(is_iterable<std::vector<int>>::value);static_assert(!is_iterable<int>::value);

检测成员类型的惯用法

// 检测 T::value_type 是否存在template<typename T, typename = void>struct has_value_type : std::false_type {};template<typename T>struct has_value_type<T, std::void_t<typename T::value_type>>     : std::true_type {};// 检测 T 是否有嵌套的 iterator 类型template<typename T, typename = void>struct has_iterator : std::false_type {};template<typename T>struct has_iterator<T, std::void_t<typename T::iterator>>     : std::true_type {};

五、技巧三:if constexpr——SFINAE 的现代替代品

C++17 的 if constexpr 是模板元编程的游戏规则改变者。大多数 SFINAE 的使用场景都可以用 if constexpr 替代,代码可读性提升一个量级。

对比:SFINAE vs if constexpr

SFINAE 写法(C++11/14):

// 三个重载,每个都要写 enable_iftemplate<typename T>typename std::enable_if<std::is_integral<T>::value>::typeprocess(T val){    std::cout << "整数: " << val << std::endl;}template<typename T>typename std::enable_if<std::is_floating_point<T>::value>::typeprocess(T val){    std::cout << "浮点: " << val << std::endl;}template<typename T>typename std::enable_if<std::is_same<T, std::string>::value>::typeprocess(T val){    std::cout << "字符串: " << val << std::endl;}

if constexpr 写法(C++17):

// 一个函数搞定template<typename T>void process(T val){if constexpr (std::is_integral_v<T>){        std::cout << "整数: " << val << std::endl;    } else if constexpr (std::is_floating_point_v<T>) {        std::cout << "浮点: " << val << std::endl;    } else if constexpr (std::is_same_v<T, std::string>) {        std::cout << "字符串: " << val << std::endl;    } else {        static_assert(always_false<T>::value, "不支持的类型");    }}// 辅助:让 static_assert 依赖模板参数template<typename T>struct always_false : std::false_type {};

区别在哪?if constexpr 在编译期求值,不满足条件的分支根本不会被编译。所以你可以在里面写只对特定类型合法的代码,不用担心编译报错。

实战:通用序列化函数

#include <iostream>#include <string>#include <vector>#include <map>#include <type_traits>template<typename T>struct always_false : std::false_type {};template<typename T>std::string serialize(const T& val){if constexpr (std::is_arithmetic_v<T>){        return std::to_string(val);    } else if constexpr (std::is_same_v<T, std::string>) {        return "\"" + val + "\"";    } else if constexpr (std::is_same_v<T, bool>) {        return val ? "true" : "false";    } else {        static_assert(always_false<T>::value,            "serialize: 不支持的类型,请特化 serialize 函数");        return "";    }}int main(){    std::cout << serialize(42) << std::endl;        // "42"    std::cout << serialize(3.14) << std::endl;      // "3.140000"    std::cout << serialize(true) << std::endl;      // "true"    std::cout << serialize(std::string("hi")) << std::endl;  // "\"hi\""    return 0;}

经验法则: 能用 if constexpr 就不要用 SFINAE。SFINAE 只在"控制函数是否参与重载决议"时才需要——比如你想根据类型条件提供不同的函数签名。


六、技巧四:变参模板(Variadic Templates)——参数包展开

C++11 引入的变参模板让你可以接受任意数量、任意类型的模板参数。

基本语法

// 递归终止条件void print(){    std::cout << std::endl;}// 递归展开template<typename T, typename... Args>void print(T first, Args... rest){    std::cout << first;if constexpr (sizeof...(rest) > 0){        std::cout << ", ";    }    print(rest...);  // 展开剩余参数}// 使用print(1, "hello", 3.14, 'A');  // 输出: 1, hello, 3.14, A

C++17 折叠表达式(Fold Expressions)

C++17 让参数包展开变得极其简洁:

#include <iostream>// 一元折叠template<typename... Args>auto sum(Args... args){    return (args + ...);  // ((a1 + a2) + a3) + ...}// 带初始值template<typename... Args>auto sum_with_zero(Args... args){    return (0 + ... + args);  // 0 + ((a1 + a2) + a3) + ...}// 逗号折叠——对每个参数执行操作template<typename... Args>void print_all(Args... args){    ((std::cout << args << " "), ...);  // 对每个 arg 执行 cout    std::cout << std::endl;}// 逻辑折叠template<typename... Args>bool all_positive(Args... args){    return ((args > 0) && ...);  // 全部 > 0 才返回 true}template<typename... Args>bool any_zero(Args... args){    return ((args == 0) || ...);  // 任意一个 == 0 就返回 true}int main(){    std::cout << sum(1, 2, 3, 4, 5) << std::endl;          // 15    print_all("Hello", 42, 3.14, "World");                  // Hello 42 3.14 World    std::cout << all_positive(1, 2, 3) << std::endl;        // true    std::cout << all_positive(1, -2, 3) << std::endl;       // false    std::cout << any_zero(1, 0, 3) << std::endl;            // true    return 0;}

实战:编译期参数数量检查

#include <type_traits>// 确保参数数量在 [Min, Max] 范围内template<size_t Min, size_t Max, typename... Args>constexpr void check_arg_count(){    static_assert(sizeof...(Args) >= Min, "参数数量不足");    static_assert(sizeof...(Args) <= Max, "参数数量过多");}// 使用template<typename... Args>void configure(Args... args){    check_arg_count<1, 5, Args...>();    // ... 配置逻辑}int main(){    configure("host", 8080);       // OK: 2 个参数    // configure();                  // 编译错误:参数数量不足    // configure(1,2,3,4,5,6,7);    // 编译错误:参数数量过多    return 0;}

实战:类型安全的 printf

#include <iostream>#include <string>#include <type_traits>// 编译期检查:printf 格式字符串和参数类型是否匹配template<typename... Args>void safe_printf(const char* fmt, Args... args){    // 编译期检查:所有参数都是算术类型或字符串    static_assert(        (std::is_arithmetic_v<Args> || std::is_same_v<Args, const char*> ||          std::is_same_v<Args, std::string>),        "safe_printf: 只支持算术类型和字符串"    );    // 运行时输出    ((std::cout << args << " "), ...);    std::cout << std::endl;}int main(){    safe_printf("%d %f %s", 42, 3.14, "hello");    // safe_printf("%d", std::vector<int>{});  // 编译错误    return 0;}

七、技巧五:模板递归——编译期的循环

模板没有循环语句,但可以用递归实现循环。这是模板元编程最原始的计算方式。

编译期阶乘

// 递归终止template<int N>struct Factorial {    static constexpr int value = N * Factorial<N - 1>::value;};// 特化:终止条件template<>struct Factorial<0> {    static constexpr int value = 1;};// 使用static_assert(Factorial<5>::value == 120);static_assert(Factorial<10>::value == 3628800);

编译期幂运算

template<int Base, int Exp>struct Power {    static constexpr long long value = Base * Power<Base, Exp - 1>::value;};template<int Base>struct Power<Base, 0> {    static constexpr long long value = 1;};static_assert(Power<2, 10>::value == 1024);static_assert(Power<3, 5>::value == 243);

C++14 的 constexpr 函数替代

注意:C++14 之后,这些都可以用 constexpr 函数替代,代码更简洁:

// C++14 constexpr 函数——等价于上面的模板递归constexpr int factorial(int n){    int result = 1;    for (int i = 2; i <= n; ++i) result *= i;    return result;}constexpr long long power(int base, int exp){    long long result = 1;    for (int i = 0; i < exp; ++i) result *= base;    return result;}static_assert(factorial(5) == 120);static_assert(power(2, 10) == 1024);

什么时候还需要模板递归? 当你需要操作类型而非值的时候。constexpr 函数只能操作值,模板递归可以操作类型。


八、技巧六:CRTP——静态多态,零开销继承

CRTP(Curiously Recurring Template Pattern)是 C++ 中实现静态多态的经典模式。它让编译器在编译期完成虚函数调用,避免虚函数表的开销。

基本结构

// 基类模板,派生类把自己作为模板参数传入template<typename Derived>class Base {public:void interface(){        // 静态转型为派生类,调用派生类的实现        static_cast<Derived*>(this)->implementation();    }void interface2(){        static_cast<Derived*>(this)->implementation2();    }};// 派生类继承 Base<Self>class Derived : public Base<Derived> {public:void implementation(){        std::cout << "Derived::implementation()" << std::endl;    }void implementation2(){        std::cout << "Derived::implementation2()" << std::endl;    }};int main(){    Derived d;    d.interface();   // 编译期绑定,无虚函数开销    d.interface2();    return 0;}

实战:为所有派生类添加统计功能

#include <iostream>#include <string>// CRTP 基类:自动为派生类添加调用计数template<typename Derived>class Countable {public:void execute(){        ++call_count_;        static_cast<Derived*>(this)->do_work();    }size_t call_count() const{ return call_count_; }private:    size_t call_count_ = 0;};class Processor : public Countable<Processor> {public:void do_work(){        std::cout << "Processing data..." << std::endl;    }};class Logger : public Countable<Logger> {public:void do_work(){        std::cout << "Logging message..." << std::endl;    }};int main(){    Processor p;    p.execute(); p.execute(); p.execute();    std::cout << "Processor called " << p.call_count() << " times" << std::endl;    Logger l;    l.execute(); l.execute();    std::cout << "Logger called " << l.call_count() << " times" << std::endl;    return 0;}

实战:CRTP 实现静态多态的对象序列化

#include <iostream>#include <string>#include <sstream>template<typename Derived>class Serializable {public:    std::string serialize() const{        std::ostringstream oss;        oss << static_cast<const Derived*>(this)->type_name() << "{";        static_cast<const Derived*>(this)->to_stream(oss);        oss << "}";        return oss.str();    }};class User : public Serializable<User> {public:    User(std::string name, int age) : name_(std::move(name)), age_(age) {}const char* type_name() const{ return "User"; }void to_stream(std::ostringstream& oss) const{        oss << "name=\"" << name_ << "\", age=" << age_;    }private:    std::string name_;    int age_;};class Config : public Serializable<Config> {public:    Config(std::string host, int port) : host_(std::move(host)), port_(port) {}const char* type_name() const{ return "Config"; }void to_stream(std::ostringstream& oss) const{        oss << "host=\"" << host_ << "\", port=" << port_;    }private:    std::string host_;    int port_;};int main(){    User u("Dr.Guo", 35);    Config c("localhost", 8080);    std::cout << u.serialize() << std::endl;  // User{name="Dr.Guo", age=35}    std::cout << c.serialize() << std::endl;  // Config{host="localhost", port=8080}    return 0;}

CRTP vs 虚函数:

维度
虚函数
CRTP
绑定时机
运行时
编译期
开销
虚函数表指针 + 间接调用
零开销(内联)
类型擦除
支持(基类指针调用)
不支持(必须知道具体类型)
适用场景
运行时多态、插件系统
编译期多态、性能敏感路径

九、技巧七:标签分发(Tag Dispatch)——编译期的策略模式

标签分发是一种用重载决议替代 if-else 的编译期技术。STL 内部大量使用这个模式。

基本原理

#include <iostream>#include <iterator>#include <vector>#include <list>// 标签类型struct random_access_tag {};struct bidirectional_tag {};struct forward_tag {};struct input_tag {};// 根据迭代器类别选择标签template<typename Iter>using iterator_category_tag = typename std::conditional<    std::is_same<typename std::iterator_traits<Iter>::iterator_category,                 std::random_access_iterator_tag>::value,    random_access_tag,    typename std::conditional<        std::is_same<typename std::iterator_traits<Iter>::iterator_category,                     std::bidirectional_iterator_tag>::value,        bidirectional_tag,        forward_tag    >::type>::type;// 随机访问迭代器的实现:直接计算距离template<typename Iter>size_t advanced_distance(Iter first, Iter last, random_access_tag){    return last - first;  // O(1)}// 其他迭代器的实现:逐步前进template<typename Iter>size_t advanced_distance(Iter first, Iter last, forward_tag){    size_t count = 0;    while (first != last) { ++first; ++count; }    return count;  // O(n)}// 统一接口:自动选择标签template<typename Iter>size_t advanced_distance(Iter first, Iter last){    return advanced_distance(first, last, iterator_category_tag<Iter>{});}int main(){    std::vector<int> vec = {1, 2, 3, 4, 5};    std::list<int> lst = {1, 2, 3, 4, 5};    // vector 的迭代器是随机访问的 → O(1)    std::cout << advanced_distance(vec.begin(), vec.end()) << std::endl;    // list 的迭代器是双向的 → O(n)    std::cout << advanced_distance(lst.begin(), lst.end()) << std::endl;    return 0;}

实战:编译期选择排序算法

#include <iostream>#include <vector>#include <algorithm>struct small_data_tag {};struct large_data_tag {};// 小数据量:插入排序(常数因子小)template<typename Iter>void sort_impl(Iter first, Iter last, small_data_tag){    // 简单的插入排序    for (auto it = first + 1; it != last; ++it) {        auto key = *it;        auto j = it - 1;        while (j >= first && *j > key) {            *(j + 1) = *j;            --j;        }        *(j + 1) = key;    }}// 大数据量:标准库排序template<typename Iter>void sort_impl(Iter first, Iter last, large_data_tag){    std::sort(first, last);}// 统一接口:根据元素数量选择算法template<typename Iter>void smart_sort(Iter first, Iter last){    auto dist = std::distance(first, last);    if (dist <= 32) {        sort_impl(first, last, small_data_tag{});    } else {        sort_impl(first, last, large_data_tag{});    }}int main(){    std::vector<int> small = {5, 2, 8, 1, 3};    std::vector<int> large(1000);    for (auto& x : large) x = rand();    smart_sort(small.begin(), small.end());  // 插入排序    smart_sort(large.begin(), large.end());  // std::sort    for (auto x : small) std::cout << x << " ";    std::cout << std::endl;    return 0;}

十、实战:一个通用的 to_string 实现

把前面学的技巧组合起来,实现一个编译期类型安全的 to_string

#include <iostream>#include <string>#include <sstream>#include <vector>#include <type_traits>template<typename T>struct always_false : std::false_type {};// 主模板:用 if constexpr 分发template<typename T>std::string to_string(const T& val){if constexpr (std::is_same_v<T, std::string>){        return val;    } else if constexpr (std::is_same_v<T, const char*> ||                          std::is_same_v<T, char*>) {        return std::string(val);    } else if constexpr (std::is_arithmetic_v<T>) {        return std::to_string(val);    } else if constexpr (std::is_same_v<T, bool>) {        return val ? "true" : "false";    } else if constexpr (requires { val.to_string(); }) {        // C++20 concept:如果有 to_string() 方法就调用        return val.to_string();    } else {        static_assert(always_false<T>::value,            "to_string: 不支持的类型");        return "";    }}// 容器特化:vectortemplate<typename T>std::string to_string(const std::vector<T>& vec){    std::string result = "[";    for (size_t i = 0; i < vec.size(); ++i) {        if (i > 0) result += ", ";        result += to_string(vec[i]);    }    result += "]";    return result;}int main(){    std::cout << to_string(42) << std::endl;    std::cout << to_string(3.14) << std::endl;    std::cout << to_string(true) << std::endl;    std::cout << to_string("hello") << std::endl;    std::cout << to_string(std::string("world")) << std::endl;    std::cout << to_string(std::vector<int>{1, 2, 3}) << std::endl;    return 0;}

十一、实战:编译期类型列表操作

这是模板元编程的"进阶但实用"场景——在编译期操作类型列表:

#include <iostream>#include <type_traits>#include <string>// 类型列表template<typename... Ts>struct TypeList {};// 获取长度template<typename List>struct Length;template<typename... Ts>struct Length<TypeList<Ts...>> {    static constexpr size_t value = sizeof...(Ts);};// 获取第 N 个类型template<typename List, size_t N>struct TypeAt;template<typename Head, typename... Tail>struct TypeAt<TypeList<Head, Tail...>, 0> {    using type = Head;};template<typename Head, typename... Tail, size_t N>struct TypeAt<TypeList<Head, Tail...>, N> {    using type = typename TypeAt<TypeList<Tail...>, N - 1>::type;};// 追加类型template<typename List, typename T>struct Append;template<typename... Ts, typename T>struct Append<TypeList<Ts...>, T> {    using type = TypeList<Ts..., T>;};// 过滤类型template<typename List, template<typename> typename Pred>struct Filter;template<template<typename> typename Pred>struct Filter<TypeList<>, Pred> {    using type = TypeList<>;};template<typename Head, typename... Tail, template<typename> typename Pred>struct Filter<TypeList<Head, Tail...>, Pred> {    using rest = typename Filter<TypeList<Tail...>, Pred>::type;    using type = typename std::conditional<        Pred<Head>::value,        typename Append<rest, Head>::type,        rest    >::type;};// 使用using MyTypes = TypeList<int, double, std::string, bool, char>;static_assert(Length<MyTypes>::value == 5);static_assert(std::is_same_v<TypeAt<MyTypes, 0>::type, int>);static_assert(std::is_same_v<TypeAt<MyTypes, 2>::type, std::string>);// 过滤出所有算术类型using ArithmeticTypes = typename Filter<MyTypes, std::is_arithmetic>::type;static_assert(Length<ArithmeticTypes>::value == 4);  // int, double, bool, charint main(){    std::cout << "类型列表长度: " << Length<MyTypes>::value << std::endl;    std::cout << "算术类型数量: " << Length<ArithmeticTypes>::value << std::endl;    return 0;}

十二、总结:模板元编程工具箱

这篇覆盖了模板元编程的 7 个核心技巧,按使用频率排序:

技巧
标准版本
核心用途
推荐指数
if constexpr
C++17
替代大部分 SFINAE,代码可读性最佳
★★★★★
<type_traits>
C++11
编译期类型判断和转换
★★★★★
变参模板 + 折叠表达式
C++11/17
任意参数的函数和类型操作
★★★★★
SFINAE + void_t
C++11/17
检测成员是否存在,控制重载决议
★★★★☆
CRTP
C++98+
静态多态,零开销继承
★★★★☆
标签分发
C++98+
编译期策略选择
★★★★☆
模板递归
C++98+
编译期类型操作(值计算用 constexpr)
★★★☆☆

我的建议:

  1. 1. C++17 项目if constexpr + <type_traits> + 折叠表达式,这三个组合能覆盖 90% 的需求
  2. 2. C++11/14 项目:SFINAE + void_t + 变参模板,稍微啰嗦但功能一样
  3. 3. 性能敏感场景:CRTP 替代虚函数,标签分发选择最优算法
  4. 4. 类型列表操作:属于进阶技巧,在写泛型库时才需要

下一篇,我们聊一个更接地气的话题——智能指针的性能陷阱。你以为用了智能指针就安全了?可能你的代码比裸指针慢 3 倍。


系列目录

📚 C++哪些有用的冷特性(共10篇)

  1. 1. C++11 已经15年了,这些特性你大概率没用过
  2. 2. 还在用裸指针和 enum?C++17 说你该升级了
  3. 3. 编译期计算有多强?constexpr 斐波那契、JSON 解析都能做
  4. 4. 模板元编程没那么可怕,这几个技巧够你应付90%的场景 ← 本篇
  5. 5. 智能指针的性能陷阱:你的代码可能比裸指针慢3倍
  6. 6. Ranges 管道操作符:C++ 终于有了函数式编程的味道
  7. 7. C++ Modules:告别 #include,编译速度提升10倍不是梦
  8. 8. C++ 原子操作的6种内存序,每种都配一个实战例子
  9. 9. C++ 废弃特性博物馆:这些东西曾经辉煌过
  10. 10. 冷特性实战:把一段"祖传代码"重构成现代 C++

系列完整代码已开源至 GitHub,持续更新中。


下一篇 → 智能指针的性能陷阱:你的代码可能比裸指针慢3倍


如果这篇文章对你有帮助,欢迎点赞、收藏、转发。有问题欢迎在评论区讨论,我会逐条回复。

© Dr.Guo's Blog

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-04-29 13:31:27 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/568065.html
  2. 运行时间 : 0.101980s [ 吞吐率:9.81req/s ] 内存消耗:4,756.23kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=93248908e871f8c6c89bfd09fe1ba4ae
  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.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000474s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000721s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000333s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000282s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000482s ]
  6. SELECT * FROM `set` [ RunTime:0.000204s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000566s ]
  8. SELECT * FROM `article` WHERE `id` = 568065 LIMIT 1 [ RunTime:0.000715s ]
  9. UPDATE `article` SET `lasttime` = 1777440687 WHERE `id` = 568065 [ RunTime:0.016524s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000420s ]
  11. SELECT * FROM `article` WHERE `id` < 568065 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000572s ]
  12. SELECT * FROM `article` WHERE `id` > 568065 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000395s ]
  13. SELECT * FROM `article` WHERE `id` < 568065 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.001437s ]
  14. SELECT * FROM `article` WHERE `id` < 568065 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000561s ]
  15. SELECT * FROM `article` WHERE `id` < 568065 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000802s ]
0.103663s