Home > Software engineering >  specialization of variadic template function for std::tuple as return type
specialization of variadic template function for std::tuple as return type

Time:12-10

I'm implementing a template function which parses a string and returns a tuple of objects, like

template <typename... Objects>
std::tuple<Objects...> convert2data(const std::string_view& input) {
    return std::tuple<Objects...>{ internal::popNext<Objects>(input)... } ;
}

// usage
auto data = convert2data<int, double>("1, 0.01") ;

I specify the expected types as template arguments. Now I'd like to get the types "directly" from a named tuple type, perhaps more convenient for a user:

using MyData = std::tuple<int, double> ; // included from some header
auto data = convert2data<MyData>("1, 0.01") ;
std::cerr << std::get<int>(data) ;
// or better
MyData data2 = convert2data("1, 0.01") ;

I'm stuck in attempts to specify a specialization for this case, e.g. this code

template <typename... Objects, class std::tuple<Objects...>>
std::tuple<Objects...> convert2data(const std::string_view& input) {
    return convert2data<Objects...>(input) ;
}

does not get compiled. Is there a way to define such specialization for a template function where template type is used in the return value?

CodePudding user response:

Something along these lines, perhaps:

template <typename Tuple, size_t... Is>
Tuple convert2dataHelper(const std::string_view& input,
                         std::index_sequence<Is...>) {
  return std::make_tuple(
      internal::popNext<std::tuple_element_t<Is, Tuple>>(input)...);
}

template <typename Tuple>
Tuple convert2data(const std::string_view& input) {
  return convert2dataHelper<Tuple>(
      input, std::make_index_sequence<std::tuple_size_v<Tuple>>{});
}

This permits convert2data<std::tuple<int, double>>("1, 0.01"); syntax.


Another approach based on partial specialization, that allows both convert2data<int, double>(...) and convert2data<std::tuple<int, double>>(...) to be called and do the same thing.

template <typename... Ts>
struct Convert2dataHelper {
  static std::tuple<Ts...> Do(const std::string_view& input) {
    return std::make_tuple(internal::popNext<Ts>(input)...);
  }
};

template <typename... Ts>
struct Convert2dataHelper<std::tuple<Ts...>> {
  static std::tuple<Ts...> Do(const std::string_view& input) {
    return Convert2dataHelper<Ts...>::Do(input);
  }
};

template <typename... Ts>
auto convert2data(const std::string_view& input) {
  return Convert2dataHelper<Ts...>::Do(input);
}
  • Related