C++17 std::visit相关可变参数模板代码语法通俗解释咨询
C++17 std::visit配套访问器代码解释
你贴的这段是C++17中配合std::visit使用的经典重载访问器实现,逐段拆解语法和逻辑如下:
完整示例代码
#include <iostream> #include <string> #include <variant> template<typename... Targs> struct VariantType : Targs... { using Targs::operator()...; }; template<typename... Targs> VariantType(Targs...) -> VariantType<Targs...>; int main() { std::variant<int, double, std::string> var; var = "Hello, world!"; std::visit( VariantType { [] (int i) { std::cout << "int: " << i << std::endl; }, [] (double d) { std::cout << "double: " << d << std::endl; }, [] (const std::string& str) { std::cout << "std::string: " << str << std::endl; } }, var ); }
逐段语法规则说明
1. 可变参数结构体定义
template<typename... Targs> struct VariantType : Targs... { using Targs::operator()...; };
这部分用到三个核心C++语法规则:
template<typename... Targs>:声明可变参数模板,支持传入任意数量的类型作为模板参数struct VariantType : Targs...:可变参数继承,让VariantType同时继承所有传入的Targs类型。示例中传入的三个参数都是lambda,每个lambda本质是编译器生成的独立匿名类,自带一个operator()调用运算符using Targs::operator()...;:C++17折叠表达式形式的using声明,作用是把所有父类(即传入的lambda类)的operator()全部引入当前类的作用域,避免继承来的同名operator()因为同名隐藏规则导致重载决议失败,让编译器能找到所有入参版本的调用运算符。
2. 类模板推导指引
template<typename... Targs> VariantType(Targs...) -> VariantType<Targs...>;
这是C++17新增的自定义类模板实参推导(CTAD)规则:当你用花括号传参构造VariantType时,编译器会自动根据传入参数的类型,推导出VariantType的模板参数类型,不需要手动显式指定模板参数——毕竟lambda的类型是编译器生成的匿名类型,开发者根本无法手动写出。
实现运行逻辑
main函数中的调用流程非常直接:
- 定义可存储
int/double/std::string三种类型的std::variant变量,赋值后实际存储的是std::string类型的值 - 构造
VariantType实例时传入三个分别对应三种variant存储类型的lambda,编译器自动生成继承了三个lambda的访问器对象,这个对象自带三个重载的operator(),分别匹配三种入参 std::visit会自动识别variant当前存储的实际类型,调用访问器中对应入参的operator()重载,最终输出std::string: Hello, world!
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

