【问题标题】:Function accepting a reference to std::variant [duplicate]接受对 std::variant 的引用的函数 [重复]
【发布时间】:2022-07-21 17:10:56
【问题描述】:

我正在尝试将值传递给接受std::variant 的函数。 我注意到我可以使用一个函数接受对变量值的 const 引用,但不能单独使用引用。考虑这段代码

#include <variant>
#include <queue>
#include <iostream>

struct Foo{ std::string msg{"foo"}; };
struct Bar{ std::string msg{"bar"}; };

using FooBar = std::variant<Foo,Bar>;

void f1(const FooBar&)
{
    std::cout << "yay" << std::endl;
}

void f2(FooBar&)
{
    std::cout << "wow" << std::endl;
}

int main()
{
    Foo f;
    Bar b;
 
    f1(f); // fine
    f1(b); // fine 
    f2(f); // compile error
}

给我错误

invalid initialization of reference of type 'FooBar&' {aka 'std::variant<Foo, Bar>&'} from expression of type 'Foo'
   42 |     f2(f);

所以第一个问题是:为什么禁止这样做? 我想不通。

我为什么要这样做? 我正在尝试使用两个访问器函数来读取和修改使用std::visit 的值,如下所示:

#include <variant>
#include <queue>
#include <iostream>

struct Foo{ std::string msg{"foo"}; };
struct Bar{ std::string msg{"bar"}; };

using FooBar = std::variant<Foo,Bar>;
   
std::string f3(const FooBar& fb)
{
    return std::visit([](auto& foobar){
        std::string ret = "yay ";
        return ret + foobar.msg;
    }, fb);
}

void f4(FooBar& fb)
{
    std::visit([](auto& foobar){
        foobar.msg += "doo";
    }, fb);
}

int main()
{
    Foo f;
    Bar b;

    std:: cout << f3(f) << " " << f3(b); // fine
    f4(f); // does not compile
}

当然不能编译

error: cannot bind non-const lvalue reference of type 'FooBar&' {aka 'std::variant<Foo, Bar>&'} to an rvalue of type 'FooBar' {aka 'std::variant<Foo, Bar>'}
   44 |     f4(f);
      |        ^

那么第二个问题:我怎样才能实现这种行为?

【问题讨论】:

  • f 不是 FooBar,但您可以从中创建(临时)FooBar。并且临时不绑定到非常量左值引用。 (如果它会编译,你不会修改f,而是临时的)。

标签: c++ c++17 std-variant


【解决方案1】:

这与std::variant 无关。以下代码具有完全相同的问题:

void foo(double){}
void bar(double&){}

int main() {
    int x = 42;
    foo(x);   // ok
    bar(x);   // cannot bind non-const lvalue reference of type 'double&' to a value of type 'int'
}

简单来说:将x 转换为double 必须涉及一个临时的double。 C++ 禁止您将临时变量作为非常量引用传递,因为 99% 的时间它是一个错误。在函数调用之后,您将无法检查 double 的值。将参数设为 const 引用或

 double y = x;
 bar(y);
 std::cout << y; // now you can inspect the value modified by the function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2023-02-22
    相关资源
    最近更新 更多