gpt4 book ai didi

c++ - std::visit 如何与 std::variant 一起使用?

转载 作者:可可西里 更新时间:2023-11-01 16:13:49 27 4
gpt4 key购买 nike

我正在查看 std:variant/std::visit文档在这里:http://en.cppreference.com/w/cpp/utility/variant/visit并在谷歌上搜索了很多,试图了解 std::visit 背后的魔力和 std::variant .

所以我的问题如下。在提供的示例中,多态 lambda 和“重载”都发生了一些“魔法”,使得从 std::variant 中提取正确的类型成为可能。 .

所以看看这个:

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);
}

对于每个 v ,这只是一个变体,如何调用正确的重载 lambda 函数?似乎有一些逻辑需要弄清楚特定 std::variant 持有的确切类型,转换它并将其分派(dispatch)给适当的功能。我的问题是它是如何工作的?同样的交易:

    std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>)
std::cout << "int with value " << arg << '\n';
else if constexpr (std::is_same_v<T, long>)
std::cout << "long with value " << arg << '\n';
else if constexpr (std::is_same_v<T, double>)
std::cout << "double with value " << arg << '\n';
else if constexpr (std::is_same_v<T, std::string>)
std::cout << "std::string with value " << std::quoted(arg) << '\n';
else
static_assert(always_false<T>::value, "non-exhaustive visitor!");
}, w);

我们将多态 lambda 作为可调用对象传递给访问者,w是一些可以容纳 int、long、double 或 std::string 的变体。找出正确类型的逻辑在哪里 using T = std::decay_t<decltype(arg)>;检索变体特定实例的实际类型?

最佳答案

我的想法是,引擎盖下std::visit构建一个函数指针数组(在编译时),它由每种类型 的实例化函数指针组成。该变体存储一个运行时类型索引 i (整数)这使得选择正确的 i 成为可能-th 函数指针并注入(inject)值。

您可能想知道我们如何在编译时数组中存储具有不同参数类型的函数指针? -> 这是通过类型删除(我认为)完成的,这意味着一个存储功能,例如一个void*参数,例如&A<T>::call :

template<typename T>
struct A
{
static call(void*p) { otherFunction(static_cast<T*>(p)); }
}

其中每个 call dispatch 到正确的函数 otherFunction带有参数(这是最后的 lambda)。类型删除意味着函数 auto f = &A<T>::call不再有类型的概念 T并有签名void(*)(void*) .

std::variant真的很复杂而且相当复杂,因为许多强大的奇特元编程技巧开始发挥作用。这个答案可能只涵盖了冰山一角:-)

关于c++ - std::visit 如何与 std::variant 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47956335/

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