gpt4 book ai didi

c++ - std::visit 的 C++17 示例中令人困惑的模板

转载 作者:IT老高 更新时间:2023-10-28 12:37:15 28 4
gpt4 key购买 nike

在 cppreference 中查看 std::visit() 页面时, https://en.cppreference.com/w/cpp/utility/variant/visit ,遇到了看不懂的代码……

这是缩略版:

#include <iomanip>
#include <iostream>
#include <string>
#include <type_traits>
#include <variant>
#include <vector>

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...)->overloaded<Ts...>;

int main() {
std::vector<std::variant<int,long,double,std::string>> vec = { 10, 15l, 1.5, "hello" };
for (auto& v : vec) {
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);
}
}

int main() 上方声明 overloaded 的两行是什么意思?

谢谢你的解释!

2019 年新增
在下面的两位先生提供了详细的解释(非常感谢!)之后,我偶然发现了非常精美的书 C++17 in Detail 中的相同代码 -了解 Bartłomiej Filipek 的新 C++ 标准的激动人心的特性!。这么好的一本书!

最佳答案

What are the two lines declaring overloaded, just above int main(), mean?

第一个

template<class... Ts>
struct overloaded : Ts...
{ using Ts::operator()...; };

是经典的类/结构声明/定义/实现。从 C++11 开始有效(因为使用可变参数模板)。

在这种情况下,overloaded从所有模板参数继承并启用(using 行)全部继承 operator() .这是 Variadic CRTP 的示例.

不幸的是,可变参数 using仅从 C++17 开始可用。

第二个

template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

是一个“演绎指南”(参见 this page 了解更多详情),它是 C++17 的一项新功能。

在你的情况下,演绎指南说当你写一些东西时

auto ov = overloaded{ arg1, arg2, arg3, arg4 };

也可以

overloaded ov{ arg1, args, arg3, arg4 };

ov变成 overloaded<decltype(arg1), decltype(arg2), decltype(arg3), decltype(arg4)>

这允许你写一些东西

overloaded
{
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
}

在 C++14 中是

auto l1 = [](auto arg) { std::cout << arg << ' '; };
auto l2 = [](double arg) { std::cout << std::fixed << arg << ' '; };
auto l3 = [](const std::string& arg) { std::cout << std::quoted(arg) << ' '; }

overloaded<decltype(l1), decltype(l2), decltype(l3)> ov{l1, l2, l3};

-- 编辑--

正如 Nemo(谢谢!)在您问题的示例代码中指出的那样,还有另一个有趣的 C++17 新特性:基类的聚合初始化。

我的意思是……当你写作时

overloaded
{
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; }
}

您正在传递三个 lambda 函数来初始化 overloaded 的三个基类.

在 C++17 之前,只有编写显式构造函数才能执行此操作。从 C++17 开始,自动运行。

此时,在我看来,展示您的 overloaded 的简化完整示例可能会很有用。在 C++17 和相应的 C++14 示例中。

我提出以下 C++17 程序

#include <iostream>

template <typename ... Ts>
struct overloaded : public Ts ...
{ using Ts::operator()...; };

template <typename ... Ts> overloaded(Ts...) -> overloaded<Ts...>;

int main ()
{
overloaded ov
{
[](auto arg) { std::cout << "generic: " << arg << std::endl; },
[](double arg) { std::cout << "double: " << arg << std::endl; },
[](long arg) { std::cout << "long: " << arg << std::endl; }
};
ov(2.1);
ov(3l);
ov("foo");
}

以及我能想象到的最好的 C++14 替代方案(也遵循 bolov 对“make”函数的建议和他的递归 overloaded 示例)。

#include <iostream>

template <typename ...>
struct overloaded;

template <typename T0>
struct overloaded<T0> : public T0
{
template <typename U0>
overloaded (U0 && u0) : T0 { std::forward<U0>(u0) }
{ }
};

template <typename T0, typename ... Ts>
struct overloaded<T0, Ts...> : public T0, public overloaded<Ts ...>
{
using T0::operator();
using overloaded<Ts...>::operator();

template <typename U0, typename ... Us>
overloaded (U0 && u0, Us && ... us)
: T0{std::forward<U0>(u0)}, overloaded<Ts...> { std::forward<Us>(us)... }
{ }
};

template <typename ... Ts>
auto makeOverloaded (Ts && ... ts)
{
return overloaded<Ts...>{std::forward<Ts>(ts)...};
}

int main ()
{
auto ov
{
makeOverloaded
(
[](auto arg) { std::cout << "generic: " << arg << std::endl; },
[](double arg) { std::cout << "double: " << arg << std::endl; },
[](long arg) { std::cout << "long: " << arg << std::endl; }
)
};
ov(2.1);
ov(3l);
ov("foo");
}

我认为这是见仁见智,但在我看来,C++17 版本更简单、更优雅。

关于c++ - std::visit 的 C++17 示例中令人困惑的模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52523816/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com