std::visit 函数中的 和 () 有啥区别?

Posted

技术标签:

【中文标题】std::visit 函数中的 和 () 有啥区别?【英文标题】:What is the difference between and () in std::visit function?std::visit 函数中的 和 () 有什么区别? 【发布时间】:2021-11-10 06:30:08 【问题描述】:

以下代码基本上是 CPP 参考上的变体示例的更“幼稚”版本。它定义了一个std::variant 类型(第[1] 行)并使用std::visit 迭代该类型的向量。在这里,我在 std::visit 函数中使用了一个仿函数(第 [2] 行),试图更好地理解 std::visit 的工作原理。

最让我困惑的是第 [4] 和 [5] 行。看来Print(带大括号)或Print()(带括号)都可以作为std::visit 函数的第一个参数。后者,即Print(),是一个实例化,因此提供一个对象作为第一个参数,这是可以理解的。我不太明白为什么前者Print 也有效。谁能解释一下这个特殊性?

using var_t = std::variant<int, long, double, std::string>; // [1]

class Print                                                // [2]  
public:
    void operator()(int arg) 
        std::cout << "Integer is " << arg << '\n';
    

    void operator()(double arg) 
        std::cout << "Double precision is " << arg << '\n';
    

    void operator()(long arg) 
        std::cout << "Long type is " << arg << '\n';
    

    void operator()(const std::string& arg) 
        std::cout << "String is " << arg << '\n';
    
;

std::vector<var_t> vec = 10, 15l, 1.5, "Hello, World", 900;   // [3]

for (auto& v : vec) 
    //std::visit(Print, v);  // [4]
    std::visit(Print(), v);    // [5]

【问题讨论】:

这是一个不同的初始化。 Print 使用聚合初始化,Print() 使用构造函数初始化。 Print是一个聚合,所以可以通过aggregate initialization初始化。 【参考方案1】:

Print() 是对 Print 类的构造函数的调用。 Print 是类Print 的列表初始化。在这种情况下,区别只是 int 列表初始化实际上是聚合初始化,并且会初始化 Print 的成员,如果有的话,构造函数不会。

在这两种情况下,您都会传递Print 的实例。

【讨论】:

以上是关于std::visit 函数中的 和 () 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

使用偏函数应用程序或 curry 与重载和 std::visit 结合使用时理解错误

std::visit 无法推断 std::variant 的类型

可以优化 std::visit 吗?

std::visit 和 MSVC 调试器的堆栈损坏“重载”结构

是否可以在没有 lambda 的情况下使用 std::visit (只是一个简单的类)? [关闭]

std::visit 和 std::variant 用法