simplifying this question, taking most of the comment into considerations, I ended up with this version, looking for some feedback
#include <iostream>
#include <tuple>
#include <cassert>
#include <type_traits>
std::tuple<std::string_view, std::string_view> split(std::string_view str, char delimiter)
{
auto pos = str.find(delimiter);
if (pos == std::string_view::npos)
{
return {str, {}};
}
return {str.substr(0, pos), str.substr(pos + 1)};
}
template <typename T>
auto parse(std::string_view str)
{
using T2 = std::unwrap_ref_decay_t<T>;
T2 res;
if constexpr (std::is_same_v<T2, std::string>) { return res = std::string(str);}
if (std::is_floating_point_v<T2>){ return res = std::stod(std::string(str));return res;}
if (std::is_integral_v<T2>) { return res = std::stol(std::string(str));}
throw std::invalid_argument("Invalid type");
}
template <typename T>
constexpr bool is_tuple = false;
template <typename T>
constexpr bool has_content = false;
template <typename T>
constexpr bool is_constructible = false;
template <typename... Ts>
constexpr bool is_tuple<std::tuple<Ts...>> = true;
template <typename... Ts>
constexpr bool has_content<std::tuple<Ts...>> = sizeof...(Ts) > 0;
template <typename... Ts>
constexpr bool is_constructible <std::tuple<Ts...>> = std::conjunction_v<std::is_default_constructible<Ts>...>;
template <typename TupleType>
requires is_tuple<TupleType> &&
has_content<TupleType> &&
is_constructible<TupleType>
auto handle(std::string_view str)
{
TupleType result;
auto parse_one = [&](auto &arg)
{
auto [ field, rest ] = split(str, ',');
arg = parse<decltype(arg)>(field);
str = rest;
};
std::apply([&](auto &...args)
{ (parse_one(args), ...); },
result);
return result;
}
int main()
{
using LineData = std::tuple<std::string, double, int64_t>;
std::string_view input_str = "first_cut,55.3,177";
LineData result = handle<LineData>(input_str);
std::cout << "Parsed values:" << '\n';
std::cout << "String value: " << std::get<0>(result) << '\n';
std::cout << "Double value: " << std::get<1>(result) << '\n';
std::cout << "Int value: " << std::get<2>(result) << '\n';
return 0;
}