将std::variant<A, B>转换为std::variant<A, B, C>。

3

我有以下代码:

std::variant<A, B> foo();
std::variant<A, B, C> bar();
std::variant<A, B, C> foobar(bool a) {
    if (a) {
        return foo();
    } else {
        return bar();
    }
}

然而,这在gcc上无法编译:
error: could not convert ‘foo()’ from ‘variant<A, B>’ to ‘variant<A,B,C>’.

有一种优雅的方法可以将 std::variant<A, B> 转换成 std::variant<A, B, C> 吗?

2
@Ripi2:那不行。variant 不能转换为其他类型的 variant - Nicol Bolas
2
一个 std::variant<A, B> 不是一个 std::variant<A, B, C>。它们是不同的类型。你为什么认为你可以在它们之间进行转换呢?记住:强制类型转换并不会转换任何东西,它只是通过不同的眼镜重新解释位。 - Jesper Juhl
2
请注意,这里适当的术语是“转换”(如错误消息中所示),而不是“强制转换”。强制转换是您在源代码中编写的内容,用于告诉编译器执行转换。 - Pete Becker
1
@PeteBecker 我把“cast”改成了“convert”。 - Ward Segers
2
可能是将std :: variant转换为具有超集类型的另一个std :: variant的重复问题,并且从那个答案中variant_cast(foo())可以正常工作。 - KamilCuk
显示剩余2条评论
2个回答

1
原则上,如果在std::variant<U...>中出现的所有类型至少与前者中的一样多,则该标准可以允许从std::variant<T...>进行隐式(如果保证成功)或显式(否则)转换,因为存在一个明确且显然的映射关系。
不幸的是,它并没有这样做。
因此,您必须编写自己的转换函数。

1

有没有一种优雅的方法将 std::variant<A, B> 转换为 std::variant<A, B, C>

我想没有。

我能想到的最好的方法是通过使用 std::visit(),例如:

std::variant<A, B, C> foobar (bool a)
 {
   if (a) 
      return std::visit([](auto && val) -> std::variant<A, B, C>
                        { return {std::forward<decltype(val)>(val)}; },
                        foo());
   else
      return bar();
 }

更通用的解决方案可以是一个convVariant()函数

template <typename R, typename T>
R convVariant (T && t)
 {
   return std::visit([](auto && val) -> R
                        { return {std::forward<decltype(val)>(val)}; },
                        std::forward<T>(t));
 }

所以,foobar() 变成:
std::variant<A, B, C> foobar (bool a)
 {
   if (a) 
      return convVariant<std::variant<A, B, C>>(foo());
   else
      return bar();
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接