Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Create class based on variadic templates

Lets imagine that we have several data flows and we need unite them to one. Capacity of flows (and type) is known at application level. So we need class that incapsulates all other classes that relates to each data flow and produces common frame based on return type of data flows. Each data flow class have next interface:

// note that there are several classes with similar interface
class FlowOne {
  using return_type = some_data;

  return_type get();
};

Main flow class will look like:

template <typename... Args>
class Main {
  using return_type = *based on Args::return_type*;
  return_type get();
};

So, here is a question: how to define Main::return_type – that should be a tuple of return_type-s from its Args? Is it possible?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Thanks

>Solution :

You can expand Args... to be std::tuple<Args...> and declare a member of that type. Now your Main class has a tuple of all Flow types:

template <typename... Args>
struct Main {
    using tuple_type = std::tuple<Args...>;
    tuple_type members;

the next step is to make a get() function that returns the .get() of all members. This can be achieved with std::apply to iterate over the tuple, and call .get() on each object. Keep in mind that, if your final get() functions return a reference, this get() should also return one (meaning auto& or auto&&).

auto get() {
    return std::apply([](auto&&... member) {
        return std::make_tuple(member.get()...);
    }, this->members);
}

As you can see, if we say decltype(get) on the member function, it will be equal to the std::tuple of Flow types:

struct FlowOne {
    using return_type = int;

    return_type get() {
        return {};
    }
};
struct FlowTwo {
    using return_type = double;
    return_type get() {
        return {};
    }
};

int main() {
    Main<FlowOne, FlowTwo> main;
    auto get = main.get();

    static_assert(std::is_same_v<decltype(get), std::tuple<int, double>>);
}

if you still wish to define a Main::return_type, you can use this using statement:

using return_type = std::tuple<typename Args::return_type...>;

we have to add typename here, because return_type is a dependant type of Args. You can read more about this on this post


Try out the full code on godbolt.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading