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

科比

我在看std:variant/std::visit在这里DOC:http://en.cppreference.com/w/cpp/utility/variant/visit也是一派很多试图了解背后的神奇std::visitstd::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,将其强制转换并将其分派给适当的函数。我的问题是如何运作?同样的交易:

    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个函数指针并插入该值。

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

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

其中每个参数都使用参数call分派到正确的函数otherFunction(这是最后的lambda)。类型擦除意味着功能auto f = &A<T>::call不再具有类型概念T并且具有签名void(*)(void*)

std::variant由于许多强大的高级元编程技巧开始发挥作用,所以它确实非常复杂且非常复杂。这个答案可能只涵盖冰山一角:-)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何使用可变参数模板将std :: variant与std :: visit一起进行?

如何使用std :: visit将std :: variant的值转换为std :: string

是否可以对与std :: variant一起使用的结构进行分组

将 boost::recursive_variant 与 std::unordered_map 一起使用

std :: visit和std :: variant用法

使用 std::bind 和 std::visit

与std :: accumulate一起使用异步

分配器如何与std :: vector一起使用?

std :: bind如何与成员函数一起使用

如何使Lambda与std :: nullopt一起使用

从std :: variant到std :: visit的可能类型返回值

具有std :: variant和std :: visit的并集模板

std::visit 不能推导出 std::variant 的类型

std :: variant <> :: get()无法与Apple LLVM 10.0一起编译

如何将std :: find()与2d std:数组一起使用?

如何使std :: fill函数与std :: map一起使用?C ++

使用传递的 lambda 调用 std::visit

将std :: find()与反向迭代器一起使用

在C ++中将QPoint与std :: map一起使用

将sigwait与std :: thread和pipe一起使用

将通用Lambda与std :: find_if一起使用

在C ++中将sprintf与std :: string一起使用

std :: is_same无法与布尔一起使用

将std :: result_of与重载方法一起使用

将 std::forward 与 Eigen::Ref 对象一起使用

将 std::conditional 与迭代器一起使用

试图获取std :: function与void *参数一起使用

是否有boost :: visit像std :: visit一样用于boost :: variant?

在从std :: variant继承的类上使用std :: visit-libstdc ++与libc ++