此代码片段取自https://en.cppreference.com/w/cpp/utility/variant/visit
using var_t = std::variant<int, long, double, std::string>;
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
for (auto& v: vec) {
// 4. another type-matching visitor: a class with 3 overloaded operator()'s
// Note: The `(auto arg)` template operator() will bind to `int` and `long`
// in this case, but in its absence the `(double arg)` operator()
// *will also* bind to `int` and `long` because both are implicitly
// convertible to double. When using this form, care has to be taken
// that implicit conversions are handled correctly.
std::visit(overloaded {
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; }
}, v);
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下using Ts::operator()...;
这里的意思吗?
在下面,这个调用了什么构造函数?与 3 个 lambda 函数?
overloaded {
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; }
}
Run Code Online (Sandbox Code Playgroud)
我认为具体的重载实例是从所有这 3 种函数类型派生的,然后访问者根据变体的类型选择正确的一个来使用。是对的吗?
我只是不完全理解这个例子。
它创建一个名为 的结构模板,overloaded
该模板继承自所有模板参数。接下来,它将所有声明的函数从其基类拉入其自己的作用域,因此当用户调用该结构的实例operator()
时,这些函数都会参与重载解析。operator()
overloaded
使用参数包扩展对所有模板参数执行相同的操作...
。
\n\n在下面,这个调用了什么构造函数?与 3 个 lambda 函数?
\n
它\xe2\x80\x99s不是构造函数,它\xe2\x80\x99s聚合初始化。在这种情况下,它使用类模板参数推导 (CTAD)来推导基类实例的模板参数overloaded
并初始化其基类实例。减去 CTAD,聚合初始化与本例相同:
struct A {};\nstruct B {};\nstruct C : A, B {};\n\nvoid f() {\n C c{A{}, B{}};\n}\n
Run Code Online (Sandbox Code Playgroud)\n实际上,您\xe2\x80\x99正在创建overloaded
结构模板的实例,使用给定的基类对象直接为其初始化一个对象,并将其传递给std::visit
. 最终效果就好像您定义了一个具有多个operator()
重载的结构(这是使用 的正常方式std::visit
)。
归档时间: |
|
查看次数: |
872 次 |
最近记录: |