- 主题:今天看见一个完全看不懂的写法
试了17能编译,14不能
【 在 urbeautiful 的大作中提到: 】
: 就是多继承啊,这个o类继承多个仿函数类,然后using是把父类的函数带到子类可见,不过这个需要20才能编译吧,17标准的话还需要写一个deduction guide吧 。
--
FROM 222.131.205.*
三点还能这么用,开眼界。
不过回头一想,这三点意思就是粗暴替换而已,只要能用逗号连起来的都可用三点?
【 在 fanci 的大作中提到: 】
:
: template<typename... Ts>
: struct Overloader : Ts...
: {
: using Ts::operator()...; // exposes operator() from every base
#发自zSMTH@桃花源v6
--
FROM 120.244.224.*
Parameter unpack, 有各种玩法,比如 x+…+0 啥的。
不过这段代码我看最奇特的是 类型推导(出花儿来),和 {} 初始化(多个)基类(居然还可以这么玩?!)
【 在 hyperLee (醉里挑灯看剑) 的大作中提到: 】
:
: 三点还能这么用,开眼界。
:
: 不过回头一想,这三点意思就是粗暴替换而已,只要能用逗号连起来的都可用三点?
--
FROM 183.179.53.*
chatgpt分析的:
这段代码使用了 C++17 中引入的类模板的折叠表达式(fold expressions)和变量模板(variable template)特性。
Overloader 是一个类模板,使用了可变参数模板(variadic template),接受任意数量的类型参数 Ts...。类模板 Overloader 继承了每个 Ts 类型的所有成员,通过使用 Ts::operator()... 来暴露所有基类的 operator()。
在 main 函数中,使用了 C++17 中引入的变量模板(variable template)特性,定义了一个名为 o 的变量,类型为 Overloader 的实例,其中 Ts... 被推导为包含两个参数类型的模板参数包 { [] (auto const& a) {std::cout << a;}, [] (float f) {std::cout << std::setprecision(3) << f;} }。这个变量模板的推导结果为 Overloader<lambda_1_type, lambda_2_type>,其中 lambda_1_type 和 lambda_2_type 是两个 lambda 表达式的类型。
在这个代码中,编译器使用了模板参数推导的规则,根据变量模板的初始化器中的参数类型推导出 Overloader 的模板参数 Ts...,从而推导出变量 o 的类型。在这个过程中,编译器使用了多个 C++17 中引入的特性,包括折叠表达式和变量模板。
chatgpt说的这个"variable template"是c++14引入的,不是c++17引入的。
https://en.cppreference.com/w/cpp/language/variable_template
所以这段代码的黑魔法除了parameter pack外,是靠variable template的自动类型推导。
--
修改:z16166 FROM 222.131.205.*
FROM 222.131.205.*
你把初始化{}当作一个builder函数就很好理解了
【 在 fanci 的大作中提到: 】
: Parameter unpack, 有各种玩法,比如 x+…+0 啥的。
: 不过这段代码我看最奇特的是 类型推导(出花儿来),和 {} 初始化(多个)基类(居然还可以这么玩?!)
--
FROM 122.224.174.*
模板再怎么用也只是替换,这个地方Overloader没有变参数的构造函数,也没有对应的结构体成员,顶楼代码是不是少写了什么?
【 在 ziqin 的大作中提到: 】
: 你把初始化{}当作一个builder函数就很好理解了
: --
发自「今日水木 on 钛星」
--
FROM 223.104.40.*
那两个lambda被编译成了(没有inline的话)两个普通函数(跟这个Overloader类没有关系的函数)。
调用的时候:
o("1.23");
o(2.34f);
会去调用这两个函数。(当然如果开了优化,这个函数调用肯定就inline了)
func(int):
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movl %edi, -20(%rbp)
movl -20(%rbp), %eax
movl %eax, -8(%rbp)
movl -20(%rbp), %eax
movl %eax, -4(%rbp)
leaq -8(%rbp), %rax
movl $.LC0, %esi
movq %rax, %rdi
call func(int)::{lambda(char const*)#1}::operator()(char const*)
const
leaq -8(%rbp), %rax
leaq 4(%rax), %rdx
movl .LC1(%rip), %eax
movd %eax, %xmm0
movq %rdx, %rdi
call func(int)::{lambda(float)#2}::operator()(float) const
nop
leave
ret
说实话,这种写法第一次见到的话确实非常困惑
【 在 ble 的大作中提到: 】
: 模板再怎么用也只是替换,这个地方Overloader没有变参数的构造函数,也没有对应的结构体成员,顶楼代码是不是少写了什么?
: 发自「今日水木 on 钛星」
--
FROM 182.150.115.*
List-initialization
【 在 ble 的大作中提到: 】
: 模板再怎么用也只是替换,这个地方Overloader没有变参数的构造函数,也没有对应的结构体成员,顶楼代码是不是少写了什么?
: 发自「今日水木 on 钛星」
--
FROM 122.224.174.*
进链接看了,楼主少写了模板推导指引
template<typename... T>
Overloader(T...) -> Overloader<T...>;
【 在 haha103 的大作中提到: 】
: 那两个lambda被编译成了(没有inline的话)两个普通函数(跟这个Overloader类没有关系的函数)。
:
: 调用的时候:
:
: o("1.23");
: o(2.34f);
:
: 会去调用这两个函数。(当然如果开了优化,这个函数调用肯定就inline了)
: ..................
发自「今日水木 on 钛星」
--
FROM 223.104.40.*
c++20不用。。。。
所以说才显得很变态 :)
【 在 ble 的大作中提到: 】
: 进链接看了,楼主少写了模板推导指引
: template<typename... T>
: Overloader(T...) -> Overloader<T...>;
: ...................
--
修改:haha103 FROM 182.150.115.*
FROM 182.150.115.*