'Neatly linking dependency tuple references specified by variadic class args

Given the following class structure in which we possess a number of different classes C#, each with unique data that is passed into a number of ledgers L<C#>, as well as possessing a number of classes S#, each depending on some subset of the classes under the C#, I have established a tuple containing all ledgers in the manager class E.

// Dependency classes
struct C {};
struct C1 : C {};
struct C2 : C {};

// Dependency data ledger
template <class T>
class L {};

// Dependency user
template <class... Cs>
struct S {
  using Deps = std::tuple<Cs...>;
  using DepRefs = std::tuple<L<Cs>&...>;
};
struct S1 : S<C1> {};
struct S2 : S<C1, C2> {};

// Manager
template <class... Ss>
class E;
template <class... Ss>
class E : public E<all_deps_no_duplicates<Ss...>, Ss...> {};
template <class... Cs, class... Ss>
class E<std::tuple<Cs...>, Ss...> {
  std::tuple<L<Cs>...> DepsData;
  std::tuple<typename Ss::DepsRefs...> DepsRefs; // Problem instantiation.
};

// Usage
int main() { E<S1, S2> e; };

What elegant solutions exist then to establish a secondary tuple containing references to each one of each dependency user's dependency ledgers? There are no duplicates in the tuple of dependency ledgers with one ledger per dependency with perhaps many dependency users each. For example, in the code given, I would want the first and second tuples in the manager class E to respectively contain:

DepsData:

std::tuple<
  L<C1>(), // 1st element: a ledger for C1
  L<C2>()  // 2nd element: a ledger for C2
>

DepsRefs:

std::tuple<
  std::tuple<L<C1>&>,         // tuple containing reference to DepsData 1st element
  std::tuple<L<C1>&, L<C2>&>  // tuple containing reference to DepsData 1st and 2nd elements
>

With both L<C1>& references in DepsRefs referring to the same ledger specified in DepsData.



Solution 1:[1]

So focusing on the reference initialization, you might do something like:

template <typename T> struct Tag{};

template <typename... Ts, typename Tuple>
std::tuple<L<Ts>&...> make_ref_tuple(Tag<std::tuple<L<Ts>&...>>, Tuple& tuple)
{
    return {std::get<L<Ts>>(tuple)...};
}

template <class... Cs, class... Ss>
class E<std::tuple<Cs...>, Ss...> {
  std::tuple<L<Cs>...> DepsData;
  std::tuple<typename Ss::DepsRefs...> DepsRefs =
     { make_ref_tuple(Tag<typename Ss::DepsRefs>{}, DepsData)... };
};

Demo

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jarod42