我正在尝试根据一些先验知识一般地解析一个字符串。 str 被传递给 convert() 并为我想要支持的类型重载,并尝试使用 std::visit() 调用正确的重载:
#include <iostream>
#include <variant>
#include <vector>
#include <charconv>
template <class ...Request, class ...Types>
constexpr bool holdsAlternative(const std::variant<Types...>& v) noexcept
{
return (std::holds_alternative<Request>(v) || ...);
}
template <typename T>
T convert(const std::string &str) = delete;
template <>
float convert<float>(const std::string &str)
{
float result = 0;
std::from_chars(str.data(), str.data() + str.size(), result);
return result;
}
template <>
int32_t convert<int32_t >(const std::string &str)
{
int32_t result = 0;
std::from_chars(str.data(), str.data() + str.size(), result);
return result;
}
using data_type = std::variant<int32_t, float, std::string>;
std::vector<data_type> Types {float{}, int32_t{}, std::string{}};
int main()
{
std::string str{"123"};
bool r = holdsAlternative<int32_t, float>(Types[1]);
if (r)
{
std::visit([&](auto &t) { return convert<decltype(t)>(str); }, Types[1]);
}
}
您的代码存在三个问题:
convert
是行不通的。但是,您可以让非专业版本抛出运行时异常。std::visit
的访问者必须对所有变体具有相同的返回类型。如果这对您来说是个问题,则取决于您想要做什么。如果你想通过convert
的输出设置变量值,你没问题:访问者都可以返回void
.std::decay_t<decltype(t)>
作为访问者的模板参数传递,因为 decltype(t)
否则会被推断为参考,并且您没有专门化,例如float&
.这里是固定代码:https://godbolt.org/z/abqv6xKde
#include <iostream>
#include <variant>
#include <vector>
#include <charconv>
template <class ...Request, class ...Types>
constexpr bool holdsAlternative(const std::variant<Types...>& v) noexcept
{
return (std::holds_alternative<Request>(v) || ...);
}
template <typename T>
T convert(const std::string &str){
throw std::logic_error("Conversion not supported\n");
};
template <>
float convert<float>(const std::string &str)
{
std::cout << "float\n";
float result = 0;
std::from_chars(str.data(), str.data() + str.size(), result);
return result;
}
template <>
int32_t convert<int32_t >(const std::string &str)
{
std::cout << "int32_t\n";
int32_t result = 0;
std::from_chars(str.data(), str.data() + str.size(), result);
return result;
}
using data_type = std::variant<int32_t, float, std::string>;
std::vector<data_type> Types {float{}, int32_t{}, std::string{}};
int main()
{
std::string str{"123"};
bool r = holdsAlternative<int32_t, float>(Types[1]);
if (r)
{
std::visit([&](auto &t) { t = convert<std::decay_t<decltype(t)>>(str); }, Types[1]);
}
}