I would like to define a function that takes an arbitrary number of containers and that number minus one arguments with respective value_types of all but the last container.
I can easily extract the value_type of the last container and use it as a return type, however, I am clueless with respect to defining the types for the arguments. I would imagine that a folding an std::integer_sequence inside std::tuple_element_t might be a way to do this but I failed to make it work.
// example: 1D interpolator
template<typename... ContainerTypes>
typename std::tuple_element_t<
sizeof...(ContainerTypes) - 1,
std::tuple<ContainerTypes...>>::value_type
interpolate(const ContainerTypes& ... /*, ??? */)
{
// (...)
return {};
}
// intended use
std::array<int, 2> x{0, 2};
std::array<double, 2> y{0, 2};
int x_query{1};
double y_interpolated{interpolate(x, y)}; // compiles
//double y_interpolated{interpolate(x, y, x_query)}; // this is what I want
As I understand, you want to transform overloads:
template <typename C1, typename CLast>
typename CLast::value_type interpolate(const C1&,
const CLast&,
typename C1::value_type);
template <typename C1, typename C2, typename CLast>
typename CLast::value_type interpolate(const C1&, const C2&,
const CLast&
typename C1::value_type, typename C2::value_type);
// ...
into variadic template.
It would be easier to have intermediate structure:
template <typename T, typename ... Ts>
struct InterpolatorImpl
{
const T& t;
std::tuple<const Ts&...> ts;
InterpolatorImpl(const T& t, const Ts&... ts) : t(t), ts(ts...) {}
typename T::value_type operator()(typename Ts::value_type...) const {/*...*/};
};
template <std::size_t...Is, typename Tuple>
auto InterpolatorHelper(std::index_sequence<Is...>, const Tuple& tuple) {
using LastType = tuple_element_t<sizeof...(Is), tuple>;
return InterpolatorImpl<LastType,
std::decay_t<std::tuple_element_t<Is, tuple>>...>
{
std::get<sizeof...(Is)>(tuple),
std::get<Is>(tuple)...
};
}
template <typename ...Ts>
auto Interpolator(const Ts&... ts) {
return InterpolatorHelper(std::make_index_sequence<sizeof...(Ts) - 1>(),
std::tie(ts...));
}
And then, call it:
std::array<int, 2> x{0, 2};
std::array<double, 2> y{0, 2};
int x_query{1};
double y_interpolated{Interpolator(x, y)(x_query)};
Or change your signature to
template <typename ... InputContainers, typename TargetContainer>
typename TargetContainer::value_type
interpolate(const std::tuple<InputContainers...>&,
const TargetContainer&,
const std::tuple<typename InputContainers::value_type...>&);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.