【问题标题】:What does "template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };" mean, and how is it being used with std::visit?“template<class...Ts> struct 重载:Ts...{ using Ts::operator()...; };”是什么意思?意思是,它是如何与 std::visit 一起使用的?
【发布时间】:2022-01-01 06:54:27
【问题描述】:

这段代码的sn-p取自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);
}

有人能解释一下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) << ' '; }
    }

我认为具体的重载实例是从所有这 3 种函数类型派生的,然后访问者会根据变体的类型选择要使用的正确的实例。对吗?

我只是不完全理解这个例子。

【问题讨论】:

    标签: c++ templates std


    【解决方案1】:

    它创建了一个名为overloaded 的结构模板,它继承自它的所有模板参数。接下来,它将所有声明的 operator() 函数从其基类中提取到自己的作用域中,因此当用户在 overloaded 结构的实例上调用 operator() 时,这些函数都会参与重载决策。

    ... 使用parameter pack expansion 对所有模板参数执行相同的操作。

    接下来,这个调用的是什么构造函数?使用 3 个 lambda 函数?

    它不是构造函数,它是aggregate initialisation。在这种情况下,它使用class template argument deduction (CTAD) 推导出overloaded 的模板参数并初始化其基类实例。减去 CTAD,聚合初始化与这种情况相同:

    struct A {};
    struct B {};
    struct C : A, B {};
    
    void f() {
        C c{A{}, B{}};
    }
    

    实际上,您正在创建 overloaded 结构模板的实例,使用给定的基类对象直接为其初始化一个对象,并将其传递给 std::visit。最终效果就像您定义了一个具有多个 operator() 重载的结构(这是使用 std::visit 的正常方式)。

    【讨论】:

      猜你喜欢
      • 2016-11-03
      • 1970-01-01
      • 1970-01-01
      • 2011-01-09
      • 1970-01-01
      • 1970-01-01
      • 2011-03-09
      • 1970-01-01
      相关资源
      最近更新 更多