指定从 std::variant 获取类型的更简洁方法?

问题描述 投票:0回答:3

我有可以简化为的代码

std::variant<float, int> v[2] = foo();
int a = std::get<decltype(a)>(v[0]);
float b = std::get<decltype(b)>(v[1]);

显然,如果

foo()
返回错误的变体,这可能会抛出异常,但这不是我的问题。 (真正的代码有一个
catch
)。我的问题是
decltype(a)
违反了“不要重复自己”原则。

是否有一种更简洁的方法来初始化 a 和 b,并且如果类型与期望不符,仍然抛出异常?特别是,当我尝试初始化 static_cast<int>(std::get<float>(v)) 时,如果变体包含浮点数,我

想要
int

c++ c++17 std-variant
3个回答
12
投票

您可以将对

get
的调用包装在隐式转换为目标类型的模板中。

template<typename... Ts>
struct variant_unwrapper {
    std::variant<Ts...> & var;
    template <typename T>
    operator T() { return std::get<T>(var); }
};

template<typename... Ts>
variant_unwrapper(std::variant<Ts...> &) -> variant_unwrapper<Ts...>;

如果你的目标是C++20,则不需要推导指南

在coliru上查看


10
投票

IMO 允许模板推导接管会很好,因此提供辅助函数应该可以完成这项工作:

template<typename T, typename...VariantParams>
void get_from(const std::variant<VariantParams...>& v, T& value)
{
    value = ::std::get<T>(v);
}

int a;

get_from(v[0], a);

5
投票

正如 @paulo 在评论中所说的那样,似乎 DRY 解决方案是使用

auto
进行声明,更改:

int a = std::get<decltype(a)>(v[0]);

至:

auto a = std::get<int>(v[0]);

您只需为类型 (

int
) 和变量 (
a
) 各命名一次。如果将声明和初始化分开,则不起作用,因此您仍然需要:

int a;
...
a = std::get<decltype(a)>(v[0]);

在这种情况下,但如果您编写所有 C++ 代码,将声明推迟到定义点,则通常不需要这样做。

© www.soinside.com 2019 - 2024. All rights reserved.