[英]Using recursive variadic template parameters in function return type
我正在尝试编写一个可变参数模板 function,它可以尝试对它的参数进行any_cast
并在第一次成功转换时返回一个variant
,我已经使用折叠表达式成功地完成了这个但是为了好玩我尝试将它写成一个递归模板我遇到了以下错误。 这是由于每个递归实例的返回类型都会更改这一事实引起的。
error: no viable conversion from returned value of type 'variant<float, std::basic_string<char>, (no argument)>' to function return type 'variant<int, float, std::basic_string<char>>'
这是我的 function
template <typename T, typename... Ts>
std::variant<T, Ts...> try_any_cast(std::any const & a)
{
if constexpr (sizeof...(Ts) > 0)
{
if (auto result = std::any_cast<T>(&a))
{
return std::any_cast<T>(a);
}
return try_any_cast<Ts...>(a);
}
else
{
throw std::bad_any_cast();
}
}
预计会像这样使用
std::any a = 5;
auto value = try_any_cast<int, float, std::string>(a);
我如何为所有实例化存储和使用原始模板参数包,以便唯一和最终的返回类型是std::variant<int, float, std::string>
?
您可以通过存储原始参数包来存储原始参数包。 好吧,听起来很奇怪,但那是因为你基本上描述了解决方案应该是什么样子而没有真正找到解决方案。 有一个辅助模板会很有帮助。 糟糕,我 go 又重复了一遍。 是时候了解一些细节了。
助手可以接受一个附加参数,即返回类型。 否则它看起来很像您当前的模板。
// Add parameter `R` for the return type
template <typename R, typename T, typename... Ts>
R try_any_cast_return(std::any const & a)
{
if constexpr (sizeof...(Ts) > 0)
{
if (auto result = std::any_cast<T>(&a))
{
return std::any_cast<T>(a);
}
return try_any_cast_return<R, Ts...>(a);
}
else
{
throw std::bad_any_cast();
}
}
一旦你有了它,你希望人们使用的模板只是一个插入所需返回类型的包装器。
template <typename... Ts>
std::variant<Ts...> try_any_cast(std::any const & a)
{
return try_any_cast_return<std::variant<Ts...>, Ts...>(a);
}
你是 go。原始参数包存储在提供给助手模板的新参数中,不会影响原始模板的使用方式。
如果有人也对我最初如何使用折叠表达式解决此问题感兴趣
template <typename... Ts>
auto try_any_cast(std::any any)
{
std::variant<Ts...> result;
if (not ((any.type() == typeid(Ts)
? (result = std::variant<Ts...>(std::any_cast<Ts>(any)), true)
: false)
|| ...))
throw std::bad_any_cast();
return result;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.