Implementation of typed tuple wrapper

116 views Asked by At

How can an implementation look like, that wraps around e.g. a std::tuple as a static list of type/value, plus a type (not contained in tuple) to refer to some kind of owner/visitor.

I want to instantiate like

constexpr auto data = data_of<a>(1, 2.0);

Background

The idea is to use a data_of<T>(...) kind of structure to to pass a list of type/data pairs into a bulk function like this.

template <typename... _Ts>
static constexpr void do_bulk_stuff(_Ts&&... _Vs)
{
    // crazy stuff happens here
}
// call it like
do_bulk_stuff
(
    data_of<a>(1, 2.0), 
    data_of<b>(3), 
    data_of<c>(4.0, 5, 6),
    // ...
);

Attempt 1

So far I ended up with a naive (not working) implementation attempt like

template <typename T, typename... Ts>
struct data_of {
    using type = T;
    using data_t = std::tuple<Ts...>;
    data_t data;
    
    constexpr data_of(Ts&&... Vs)
    : data(Vs...)
    {}
};

Goal

My goal is to achieve a result like this data_of<a> instance pseudo code example

{
    // meta
    type = a;
    data_t = std::tuple<int,double>;

    // runtime
    data = [1, 2.0];
}
1

There are 1 answers

0
StoryTeller - Unslander Monica On BEST ANSWER

The issue inherent to your attempt is that class template argument deduction is simply not like its function counterpart. There will be no deduction if any of the class template's arguments is explicitly specified. You fail because the trailing pack is always specified (by omission) as empty.

The solution is to shift the burden onto the mechanism that allows you to specify only part of the arguments: function templates.

template <typename T, typename... Ts>
struct data_of_t {
    using type = T;
    using data_t = std::tuple<Ts...>;
    data_t data;
    
    constexpr data_of_t(Ts&&... vs)
    : data(std::forward<Ts>(vs)...)
    {}
};

template<typename T, typename... Ts>
constexpr auto data_of(Ts&&... vs) {
    return data_of_t<T, Ts...>(std::forward<Ts>(vs)...);
}

Now the type of the expression data_of<a>(1, 2.0) has the same "meta" properties you are after.