MSa*_*ers 4 c++ c++17 std-variant
我有可以简化为的代码
std::variant<float, int> v[2] = foo();
int a = std::get<decltype(a)>(v[0]);
float b = std::get<decltype(b)>(v[1]);
Run Code Online (Sandbox Code Playgroud)
显然,如果返回错误的变体,这可能会抛出foo()异常,但这不是我的问题。(真正的代码有一个catch)。我的问题是这decltype(a)违反了“不要重复自己”原则。
是否有一种更简洁的方法来初始化 a 和 b,并且如果类型与预期不匹配,仍然会抛出异常?特别是,当我static_cast<int>(std::get<float>(v))尝试初始化int.
Cal*_*eth 12
您可以将调用包装get在隐式转换为目标类型的模板中。
template<typename... Ts>
struct variant_unwrapper {
std::variant<Ts...> & var;
template <typename T>
operator T() { return std::get<T>(var); }
};
Run Code Online (Sandbox Code Playgroud)
Mar*_*k R 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);
Run Code Online (Sandbox Code Playgroud)
正如@paulo 在评论中所说,似乎 DRY 解决方案是用于auto声明,更改:
int a = std::get<decltype(a)>(v[0]);
Run Code Online (Sandbox Code Playgroud)
到:
auto a = std::get<int>(v[0]);
Run Code Online (Sandbox Code Playgroud)
您只需为类型 ( int) 和变量 ( a) 各命名一次。如果将声明和初始化分开,则不起作用,因此您仍然需要:
int a;
...
a = std::get<decltype(a)>(v[0]);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,但如果您编写的所有 C++ 代码都将声明推迟到定义点,则通常不需要这样做。