乐于分享
好东西不私藏

std::visit深入理解及源码分析

std::visit深入理解及源码分析

目录

1.简介

2.基础用法

3.高级技巧

4.注意事项

5.与其他访问方式对比

6.底层原理

6.1.原理分析

6.2.源码分析

6.2.1.从入参限制只允许传入 variant

6.2.2.std::visit 入口函数(编译期核心)

6.2.3._Visit_impl 策略选择器(性能核心)

6.2.4._Visit_strategy 分发策略实现

6.2.5.宏代码生成(最精妙的部分)

6.2.6.最终分发 _Variant_dispatcher

7.总结


1.简介

设计模式之访问者模式

C++三剑客之std::variant(一) : 使用

C++三剑客之std::variant(二):深入剖析

        std::visit 是 C++17 引入的标准库函数模板,定义于 <variant> 头文件,用于安全、类型完备地访问 std::variant 中当前存储的值,是访问 variant 的推荐方式。它基于访问者模式 (Visitor Pattern) 实现,自动匹配 variant 活跃类型并调用对应处理逻辑,避免手动判断 type index 或冗长 switch-case,杜绝未定义行为。

        语法格式:

// C++17 基础版本,返回类型自动推导template <class Visitorclass... Variants>constexpr /* 推导类型 */ visit(Visitor&& vis, Variants&&... vars);// C++20 显式指定返回类型版本template <class Rclass Visitorclass... Variants>constexpr R visit(Visitor&& vis, Variants&&... vars);
  • Visitor
    :可调用对象(函数、lambda、函数对象),需支持所有 variant 类型组合的调用
  • Variants
    :一个或多个 std::variant 对象,visit 会组合所有 variant 的活跃类型调用 visitor
  • 返回值
    :visitor 调用结果,C++20 可显式指定返回类型 R

2.基础用法

1.单 variant 访问(lambda 作为访问者)

#include<variant>#include<iostream>#include<string>intmain(){    std::variant<intdouble, std::string> var;    var = 42;    std::visit([](auto&& val) {        using T = std::decay_t<decltype(val)>;        if constexpr (std::is_same_v<T, int>)            std::cout << "整数: " << val << "\n";        else if constexpr (std::is_same_v<T, double>)            std::cout << "浮点数: " << val << "\n";        else if constexpr (std::is_same_v<T, std::string>)            std::cout << "字符串: " << val << "\n";    }, var);    var = 3.14;    std::visit([](auto val) { std::cout << "值: " << val << "\n"; }, var);    var = "Hello C++17";    std::visit([](const auto& val) { std::cout << "值: " << val << "\n"; }, var);    return 0;}

2.多 variant 组合访问

#include<variant>#include<iostream>#include<string>using VarType = std::variant<intdouble, std::string>;intmain(){    VarType a = 10;    VarType b = 3.14;    VarType c = "Hello";    // 组合两个 variant 的所有可能类型组合    std::visit([](auto&& x, auto&& y) {        std::cout << "x: " << x << ", y: " << y << "\n";    }, a, b);    // 组合三个 variant    std::visit([](auto&& x, auto&& y, auto&& z) {        std::cout << "x: " << x << ", y: " << y << ", z: " << z << "\n";    }, a, b, c);    return 0;}

输出:

3.高级技巧

1.重载 lambda 访问者(推荐)

C++17 可通过继承多个 lambda 实现重载访问,需要定义辅助结构体:

#include <variant>#include <iostream>#include <string>// 辅助模板:继承多个 lambda 并 using 其 operator()template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };// 推导指引:让编译器自动推导模板参数template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;{}int main() {    std::variant<intdouble, std::stringvar = 42.5;    // 使用重载 lambda 处理不同类型    std::visit(overloaded{        [](int i) { std::cout << "整数: " << i << "\n"; },        [](double d) { std::cout << "浮点数: " << d << "\n"; },        [](const std::string& s) { std::cout << "字符串: " << s << "\n"; }    }, var);    return 0;}

2.函数对象作为访问者

#include<variant>#include<iostream>#include<string>struct PrintVisitor {    voidoperator()(int i)const{ std::cout << "整数: " << i << "\n"; }    voidoperator()(double d)const{ std::cout << "浮点数: " << d << "\n"; }    voidoperator()(const std::string& s)const{ std::cout << "字符串: " << s << "\n"; }};intmain(){    std::variant<intdouble, std::string> var;    var = "C++17";    std::visit(PrintVisitor{}, var);    return 0;}

3.带返回值的访问

#include<variant>#include<iostream>#include<string>#include<string_view>using VarType = std::variant<intdouble, std::string>;// 返回值类型统一为 std::stringstd::string format_value(const VarType& var){    return std::visit([](auto&& val) -> std::string {        using T = std::decay_t<decltype(val)>;        if constexpr (std::is_same_v<T, int>)            return "整数: " + std::to_string(val);        else if constexpr (std::is_same_v<T, double>)            return "浮点数: " + std::to_string(val);        else if constexpr (std::is_same_v<T, std::string>)            return "字符串: " + val;    }, var);}intmain(){    VarType a = 42;    VarType b = 3.14159;    VarType c = "Hello World";    std::cout << format_value(a) << "\n";    std::cout << format_value(b) << "\n";    std::cout << format_value(c) << "\n";    return 0;}

4.C++20 显式指定返回类型

#include<variant>#include<iostream>#include<string>intmain(){    std::variant<intdouble, std::string> var = 3.14;    // 显式指定返回类型为 double    double result = std::visit<double>([](auto val) {        using T = std::decay_t<decltype(val)>;        if constexpr (std::is_same_v<T, int>)            return static_cast<double>(val);        else if constexpr (std::is_same_v<T, double>)            return val;        else if constexpr (std::is_same_v<T, std::string>)            return std::stod(val);    }, var);    std::cout << "转换为 double: " << result << "\n";    return 0;}

4.注意事项

  • 类型完备性检查
    :visitor 必须处理 variant 所有可能类型,否则编译失败,这是编译期安全保障,避免遗漏类型处理
  • constexpr 支持
    :C++17 起 visit 可在常量表达式中使用,适用于编译期计算
  • 值类别处理
    :可通过完美转发(auto&&)保持原始值类别,避免不必要拷贝
  • 性能特点
    :visit 通常零开销抽象,生成的代码与手动编写的 switch-case 相当,某些编译器甚至更优
  • 空 variant 处理
    :若 variant 无活跃值(默认构造且未赋值),调用 visit 会抛出 std::bad_variant_access 异常
  • 多 variant 组合
    :当传递多个 variant 时,visit 会生成所有可能类型组合的调用,visitor 必须支持所有组合

5.与其他访问方式对比

访问方式
优点
缺点
适用场景
std::visit
类型安全、编译期检查完备性、支持多 variant
需定义访问者
大多数场景,推荐使用
std::get_if
简单直接、可选择性访问
需手动检查类型、可能遗漏处理
仅需访问特定类型
std::holds_alternative
明确判断类型
需配合 get 使用、冗长
类型判断后再访问
手动 switch (type ())
直观
易出错、维护困难、无编译期检查
不推荐,已被 visit 替代

6.底层原理

6.1.原理分析

  std::visit 本质是 「编译期生成类型分发逻辑 + 运行期索引跳转」,是零开销的静态多态实现,完全没有虚函数开销,也是 C++ 类型安全的核心保障。

编译期(核心:生成分发逻辑 + 类型安全检查)

  • 提取 variant 所有类型
    :从模板参数中拿到 <int, double, std::string>
  • 生成全部分支
    :为每一种类型,生成调用 visitor 的代码(比如 visitor(int)visitor(double));
  • 类型完备性检查
    :强制要求 visitor 能处理所有类型,少一个都直接编译报错(这是它类型安全的根源)。

最终编译器生成一张 **「类型索引 → 函数调用」的跳转表 **(函数指针数组 / 优化后的 switch-case)。

运行期(核心:索引查表,直接跳转)

  • 读取 variant.index() 获取当前类型编号;
  • 根据编号从跳转表中找到对应的函数,直接调用访问者逻辑。

用 20 行代码模拟标准库的核心原理,一看就懂:

#include <iostream>#include <string>#include <variant>// 1. 复用之前的重载lambda工具template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;// 2. 手写简化版 std::visit(核心原理!)template <typename Visitor, typename... Types>void my_visit(Visitor&& vis, std::variant<Types...>& var) {    // 运行期:获取variant的类型索引    const size_t idx var.index();    // 编译期生成的switch分发逻辑(核心!)    switch(idx) {        case 0vis(std::get<0>(var)); break;  // 匹配第一个类型        case 1vis(std::get<1>(var)); break;  // 匹配第二个类型        case 2vis(std::get<2>(var)); break;  // 匹配第三个类型        defaultthrow std::bad_variant_access();    }}// 测试int main() {    std::variant<intdouble, std::stringvar = 3.14;    // 用手写的my_visit,和标准库效果完全一致    my_visit(overloaded{        [](int) { std::cout << "int\n"; },        [](double) { std::cout << "double\n"; },        [](std::string) { std::cout << "string\n"; }    }, var);}

✅ 输出:double

6.2.源码分析

以vs2022的std::visit实现为例进行分析,先上源码:

_EXPORT_STD template <class _Callableclass... _Variants, class = void_t<_As_variant<_Variants>...>>constexpr _Variant_visit_result_t<_Callable, _As_variant<_Variants>...> visit(_Callable&& _Obj, _Variants&&... _Args) {    // Invoke _Obj with the contained values of _Args...    constexpr auto _Size = _Variant_total_states<_Remove_cvref_t<_As_variant<_Variants>>...>;    using _ListOfIndexLists =        _Meta_list<_Meta_as_list<make_index_sequence<1 + variant_size_v<_Remove_cvref_t<_As_variant<_Variants>>>>>...>;    using _ListOfIndexVectors =        _Meta_transform<_Meta_quote<_Meta_as_integer_sequence>, _Meta_cartesian_product<_ListOfIndexLists>>;    using _Ret = _Variant_visit_result_t<_Callable, _As_variant<_Variants>...>;    static_assert(_Variant_all_visit_results_same<_Ret, _Callable, _Meta_list<>, _As_variant<_Variants>...>,        "visit() requires the result of all potential invocations to have the same type and value category "        "(N4950 [variant.visit]/5).");    return _STD _Visit_impl<_Size, _Ret, _ListOfIndexVectors>(        static_cast<_Callable&&>(_Obj), static_cast<_Variants&&>(_Args)...);}template <size_t _Size, class _Retclass _ListOfIndexVectorsclass _Callableclass... _Variants>constexpr _Ret _Visit_impl(_Callable&& _Obj, _Variants&&... _Args) {    constexpr int _Strategy = _Size == 1   ? 0                            : _Size <= 4   ? 1                            : _Size <= 16  ? 2                            : _Size <= 64  ? 3                            : _Size <= 256 ? 4                                           : -1;    return _Visit_strategy<_Strategy>::template _Visit2<_Ret, _ListOfIndexVectors>(        _STD _Variant_visit_index1(0static_cast<_As_variant<_Variants>&>(_Args)...), static_cast<_Callable&&>(_Obj),        static_cast<_As_variant<_Variants>&&>(_Args)...);}template <int _Strategy>struct _Visit_strategy;template <>struct _Visit_strategy<-1> {    // Fallback strategy for visitations with too many total states for the following "switch" strategies.    template <class _Retclass _ListOfIndexVectorsclass _Callableclass... _Variants>    static constexpr _Ret _Visit2(        size_t _Idx, _Callable&& _Obj, _Variants&&... _Args) { // dispatch a visitation with many potential states        constexpr size_t _Size = _Variant_total_states<_Remove_cvref_t<_Variants>...>;        static_assert(_Size > 256);        constexpr auto& _Array =            _Variant_dispatch_table<_Ret, _ListOfIndexVectors, _Callable, _Meta_list<_Variants...>>::_Array;        return _Array[_Idx](static_cast<_Callable&&>(_Obj), static_cast<_Variants&&>(_Args)...);    }};template <>struct _Visit_strategy<0> {    template <class _Retclassclass _Callable>    static constexpr _Ret _Visit2(size_t, _Callable&& _Obj) { // dispatch a visitation with 4^0 potential states        ifconstexpr(is_void_v<_Ret>){            return static_cast<void>(static_cast<_Callable&&>(_Obj)());        } else {            return static_cast<_Callable&&>(_Obj)();        }    }};#define _STL_CASE(n)                                                                                  \    case (n):                                                                                         \        if constexpr ((n) < _Size) {                                                                  \            using _Indices = _Meta_at_c<_ListOfIndexVectors, (n)>;                                    \            return _Variant_dispatcher<_Indices>::template _Dispatch2<_Ret, _Callable, _Variants...>( \                static_cast<_Callable&&>(_Obj), static_cast<_Variants&&>(_Args)...);                  \        }                                                                                             \        _STL_UNREACHABLE;                                                                             \        [[fallthrough]]#define _STL_VISIT_STAMP(stamper, n)                                               \    constexpr size_t _Size = _Variant_total_states<_Remove_cvref_t<_Variants>...>; \    static_assert(_Size > (n) / 4 && _Size <= (n));                                \    switch (_Idx) {                                                                \        stamper(0, _STL_CASE);                                                     \    default:                                                                       \        _STL_UNREACHABLE;                                                          \    }template <>struct _Visit_strategy<1> {    template <class _Retclass _ListOfIndexVectorsclass _Callableclass... _Variants>    static constexpr _Ret _Visit2(size_t _Idx, _Callable&& _Obj, _Variants&&... _Args) {        // dispatch a visitation with 4^1 potential states        _STL_STAMP(4, _STL_VISIT_STAMP);    }};template <>struct _Visit_strategy<2> {    template <class _Retclass _ListOfIndexVectorsclass _Callableclass... _Variants>    static constexpr _Ret _Visit2(size_t _Idx, _Callable&& _Obj, _Variants&&... _Args) {        // dispatch a visitation with 4^2 potential states        _STL_STAMP(16, _STL_VISIT_STAMP);    }};template <>struct _Visit_strategy<3> {    template <class _Retclass _ListOfIndexVectorsclass _Callableclass... _Variants>    static constexpr _Ret _Visit2(size_t _Idx, _Callable&& _Obj, _Variants&&... _Args) {        // dispatch a visitation with 4^3 potential states        _STL_STAMP(64, _STL_VISIT_STAMP);    }};template <>struct _Visit_strategy<4> {    template <class _Retclass _ListOfIndexVectorsclass _Callableclass... _Variants>    static constexpr _Ret _Visit2(size_t _Idx, _Callable&& _Obj, _Variants&&... _Args) {        // dispatch a visitation with 4^4 potential states        _STL_STAMP(256, _STL_VISIT_STAMP);    }};#define _STL_STAMP4(n, x) \    x(n);                 \    x(n + 1);             \    x(n + 2);             \    x(n + 3)#define _STL_STAMP16(n, x) \    _STL_STAMP4(n, x);     \    _STL_STAMP4(n + 4, x); \    _STL_STAMP4(n + 8, x); \    _STL_STAMP4(n + 12, x)#define _STL_STAMP64(n, x)   \    _STL_STAMP16(n, x);      \    _STL_STAMP16(n + 16, x); \    _STL_STAMP16(n + 32, x); \    _STL_STAMP16(n + 48, x)#define _STL_STAMP256(n, x)   \    _STL_STAMP64(n, x);       \    _STL_STAMP64(n + 64, x);  \    _STL_STAMP64(n + 128, x); \    _STL_STAMP64(n + 192, x)#define _STL_STAMP(n, x) x(_STL_STAMP##n, n)

6.2.1.从入参限制只允许传入 variant

_EXPORT_STD template <class _Callableclass... _Variants, class = void_t<_As_variant<_Variants>...>>constexpr _Variant_visit_result_t<_Callable, _As_variant<_Variants>...> visit(_Callable&& _Obj, _Variants&&... _Args){    //。。。}

用到了std::void_t,不理解的可以参考下面内容:C++17之std::void_t

再来看一下_As_variant :

// 接收:普通左值 varianttemplate <class... _Types>variant<_Types...>& _As_variant_impl(variant<_Types...>&);// 接收:const 左值 varianttemplate <class... _Types>const variant<_Types...>& _As_variant_impl(const variant<_Types...>&);// 接收:普通右值 varianttemplate <class... _Types>variant<_Types...>&& _As_variant_impl(variant<_Types...>&&);// 接收:const 右值 varianttemplate <class... _Types>const variant<_Types...>&& _As_variant_impl(const variant<_Types...>&&);//declval 编译期生成一个临时的 _Ty 类型值(不创建真实对象)。template <class _Ty>using _As_variant = // Deduce variant specialization from a derived type    decltype(_STD _As_variant_impl(_STD declval<_Ty>()));

关键点:

  • 只有声明,没有函数体
    不需要实现,我们只在编译期用它推导类型decltype)。
  • 全覆盖所有值类别
    左值、右值、const、非 const 全部匹配,不遗漏任何一种 variant 参数。
  • 支持派生类
    如果你写了一个类 class MyVar : public std::variant<int> {},它能隐式转换为基类 variant,所以也能匹配这四个函数。

void_t<_As_variant<_Variants>...>

  • 如果 _Variants 是 variant / 派生类 → 推导成功,模板生效;
  • 如果传入 int/string 等非 variant → 推导失败,直接编译报错

✅ 这就是 std::visit只允许传入 variant 的底层原因。

6.2.2.std::visit 入口函数(编译期核心)

_EXPORT_STD template <    class _Callable,        // 访问者(lambda/函数/函数对象)    class... _Variants,     // 一个/多个 variant    class = void_t<_As_variant<_Variants>...>  // 约束:参数必须是variant>constexpr _Variant_visit_result_t<_Callable, _As_variant<_Variants>...> visit(_Callable&& _Obj, _Variants&&... _Args) {    // 1. 计算【所有variant类型组合的总状态数】(笛卡尔积)    constexpr auto _Size = _Variant_total_states<_Remove_cvref_t<_As_variant<_Variants>>...>;    // 2. 为每个variant生成索引列表:如variant<int,double> → [0,1]    using _ListOfIndexLists = _Meta_list<        _Meta_as_list<make_index_sequence<1 + variant_size_v<...>>>...    >;    // 3. 计算索引的【笛卡尔积】(多variant核心)    using _ListOfIndexVectors = _Meta_transform<        _Meta_quote<_Meta_as_integer_sequence>,         _Meta_cartesian_product<_ListOfIndexLists>    >;    // 4. 推导返回值类型    using _Ret = _Variant_visit_result_t<_Callable, _As_variant<_Variants>...>;    // 5. 强制校验:所有类型分支的返回值 类型/值类别 必须完全一致(C++标准强制要求)    static_assert(_Variant_all_visit_results_same<...>,        "visit() requires the result of all potential invocations to have the same type...");    // 6. 转发给实现函数    return _STD _Visit_impl<_Size, _Ret, _ListOfIndexVectors>(        static_cast<_Callable&&>(_Obj),  // 完美转发        static_cast<_Variants&&>(_Args)...);}

关键点:

  • _Variant_total_states
    总状态数 = 所有 variant 类型数量的乘积例:variant<int,double> × variant<string,bool> → 2×2=4 种状态
//[1]_EXPORT_STD template <class _Ty>struct variant_size// undefinedtemplate <class _Ty>struct variant_size<const _Ty> : variant_size<_Ty>::type {};template <class _Ty>struct _CXX20_DEPRECATE_VOLATILE variant_size<volatile _Ty> : variant_size<_Ty>::type {};template <class _Ty>struct _CXX20_DEPRECATE_VOLATILE variant_size<const volatile _Ty> : variant_size<_Ty>::type {};_EXPORT_STD template <class _Ty>constexpr size_t variant_size_v = variant_size<_Ty>::value;template <class... _Types>struct variant_size<variant<_Types...>> : integral_constant<size_tsizeof...(_Types)> {};//[2]template <class... _Variants>constexpr size_t _Variant_total_states =    (size_t{1} * ... * (variant_size_v<_Variants> + 1)); // +1 to account for the valueless state
  • make_index_sequence编译期根据参数长度生成序列,不明白的可参考:

C++14之std::index_sequence和std::make_index_sequence的使用和原理分析

  • _Meta_cartesian_product(核心黑科技)
    编译期生成所有类型组合的索引(0,0)、(0,1)、(1,0)、(1,1)
  • 静态断言
    杜绝错误:比如访问者int分支返回intdouble分支返回string直接编译报错
  • 完美转发static_cast<T&&>
     = std::forward,保留左值 / 右值,零拷贝

6.2.3._Visit_impl 策略选择器(性能核心)

template <size_t _Size, class _Retclass _ListOfIndexVectorsclass _Callableclass... _Variants>constexpr _Ret _Visit_impl(_Callable&& _Obj, _Variants&&... _Args) {    // 根据总状态数,自动选择最优分发策略    constexpr int _Strategy =         _Size == 1   ? 0    // 只有1种类型:直接调用      : _Size <= 4   ? 1    // ≤4:switch 4个case      : _Size <= 16  ? 2    // ≤16:switch 16个case      : _Size <= 64  ? 3    // ≤64:switch 64个case      : _Size <= 256 ? 4    // ≤256:switch 256个case                     : -1;  // >256:函数指针数组(避免代码膨胀)    // 计算【全局索引】:把多个variant的index合并为一个数字    size_t _Idx = _Variant_visit_index1(0static_cast<_As_variant<_Variants>&>(_Args)...);    // 转发给对应策略    return _Visit_strategy<_Strategy>::template _Visit2<_Ret, _ListOfIndexVectors>(        _Idx, std::forward<_Callable>(_Obj), std::forward<_Variants>(_Args)...);}

关键点:

  • 为什么分策略?
    • switch-case
      :CPU 分支预测拉满,速度最快(小状态数首选);
    • 函数指针数组
      :避免switch生成上万行代码,内存更优(大状态数首选)。
  • _Variant_visit_index1
    把多个variant.index() 压缩成一个全局索引,用于查表 /switch。例:var1.index()=1 + var2.index()=0 → 全局索引 =2
_NODISCARD constexpr size_t _Variant_visit_index1(const size_t _Acc) noexcept {    return _Acc;}template <class _FirstTyclass... _RestTys>_NODISCARD constexpr size_t _Variant_visit_index1(    size_t _Acc, const _FirstTy& _First, const _RestTys&... _Rest) noexcept {    // calculate a canonical index from the biased indices of the variants _First and _Rest...    _Acc += (_First.index() + 1) * _Variant_total_states<_RestTys...>;    return _STD _Variant_visit_index1(_Acc, _Rest...);

6.2.4._Visit_strategy 分发策略实现

策略 -1:超大状态数(>256)→ 函数指针数组

template <>struct _Visit_strategy<-1> {    template <class _Retclass _ListOfIndexVectorsclass _Callableclass... _Variants>    static constexpr _Ret _Visit2(size_t _Idx, _Callable&& _Obj, _Variants&&... _Args) {        static_assert(_Size > 256);        // 编译期生成:函数指针数组(每个元素对应一种类型组合)        constexpr auto& _Array = _Variant_dispatch_table<...>::_Array;        // 运行期:O(1) 索引查表调用        return _Array[_Idx](std::forward<_Callable>(_Obj), std::forward<_Variants>(_Args)...);    }};

策略 0:只有 1 种状态 → 直接调用(无分发开销)

template <>struct _Visit_strategy<0> {    template <class _Retclassclass _Callable>    static constexpr _Ret _Visit2(size_t, _Callable&& _Obj) {        // 直接调用访问者,无任何跳转        ifconstexpr(is_void_v<_Ret>)            return static_cast<void>(std::forward<_Callable>(_Obj)());        else            return std::forward<_Callable>(_Obj)();    }};

6.2.5.宏代码生成(最精妙的部分)

STL 用宏批量生成 switch-case,不用手写重复代码。

1.单个 case 宏

#define _STL_CASE(n) \    case (n): \        if constexpr ((n) < _Size) { \            using _Indices = _Meta_at_c<_ListOfIndexVectors, (n)>; \            // 核心:根据索引调用std::get取值,转发给访问者            return _Variant_dispatcher<_Indices>::template _Dispatch2<_Ret, ...>( \                std::forward<_Callable>(_Obj), std::forward<_Variants>(_Args)...); \        } \        _STL_UNREACHABLE; \        [[fallthrough]]

2.批量生成 case 宏(4/16/64/256 个)

// 生成4个case#define _STL_STAMP4(n, x)  x(n);x(n+1);x(n+2);x(n+3)// 生成16个case(4×4)#define _STL_STAMP16(n, x) _STL_STAMP4(n,x);_STL_STAMP4(n+4,x);...// 生成64/256个case#define _STL_STAMP64 ...#define _STL_STAMP256 ...// 顶层宏:触发生成#define _STL_STAMP(n, x) x(_STL_STAMP##n, n)

3.策略 1~4:switch 分发(最常用)

// 策略1:≤4 个状态template <> struct _Visit_strategy<1> {    template <...> static constexpr _Ret _Visit2(...) {        _STL_STAMP(4, _STL_VISIT_STAMP); // 编译期展开:switch + 4个case    }};// 策略2:≤16 → 16个case// 策略3:≤64 → 64个case// 策略4:≤256 → 256个case

6.2.6.最终分发 _Variant_dispatcher

这是最底层调用,等价于我们手写的:

case 2: vis(std::get<1>(var1), std::get<0>(var2));

7.总结

  • 优先使用重载 lambda 模式
    :通过 overloaded 结构体组合多个 lambda,代码清晰、类型安全
  • 保持 visitor 简洁
    :每个重载处理单一类型,避免复杂逻辑,提升可读性与可维护性
  • 使用完美转发
    :参数使用 auto&& 避免不必要拷贝,提高性能
  • 明确返回类型
    :当返回类型不统一时,显式指定返回类型,避免编译错误
  • 处理空 variant
    :确保 variant 始终有活跃值,或在访问前检查

std::visit 是 C++17 为 std::variant 提供的核心访问机制,通过访问者模式实现类型安全、编译期完备性检查和高效的类型分发。它不仅简化了 variant 的使用,还大幅提升了代码的安全性和可维护性,是现代 C++ 中处理变体类型的首选工具。

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-06-07 09:49:29 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/721572.html
  2. 运行时间 : 0.099967s [ 吞吐率:10.00req/s ] 内存消耗:4,803.91kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=2ede83bec981f57a6d1c707067d381ff
  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.000501s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000656s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000372s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000357s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000602s ]
  6. SELECT * FROM `set` [ RunTime:0.000300s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000562s ]
  8. SELECT * FROM `article` WHERE `id` = 721572 LIMIT 1 [ RunTime:0.002448s ]
  9. UPDATE `article` SET `lasttime` = 1780796969 WHERE `id` = 721572 [ RunTime:0.013537s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000254s ]
  11. SELECT * FROM `article` WHERE `id` < 721572 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000466s ]
  12. SELECT * FROM `article` WHERE `id` > 721572 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000385s ]
  13. SELECT * FROM `article` WHERE `id` < 721572 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000742s ]
  14. SELECT * FROM `article` WHERE `id` < 721572 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000707s ]
  15. SELECT * FROM `article` WHERE `id` < 721572 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000695s ]
0.101740s