Structural tuple-like / Wrapping a variadic set of template parameters values in a struct

  c++, c++20, constexpr, tuples

I find myself wanting/needing to use a variadic composite type as a template parameter. Unfortunately, std::tuple<> is not a structural type, which makes the obvious approach a no-go:

#include <tuple>

template<typename... Ts>
struct composite {
  std::tuple<Ts...> operands;
};

template<auto v>
void foo() {}

int main() {
  constexpr composite tmp{std::make_tuple(1,2,3)};
  foo<tmp>();  // <----- Nope!
}

Is there a reasonable way to build such a composite in a manner that works as a structural type?

Since the MCVE in isolation is trivially solvable as "just make foo() a variadic template", here’s a more representative example:

On godbolt

#include <concepts>
#include <tuple>

template <typename T, template <typename...> typename U>
concept TemplatedConfig = requires(T x) {
  { U(x) } -> std::same_as<T>;
  // A few more things identifying T as a valid config
};

template<auto Config>
struct proc;

// Basic
struct Basic {};

template<Basic v>
struct proc<v> {
    constexpr int foo() { return 0;}
};

// Annotated
template<typename T>
struct Annotated {
    T v;
    int annotation;
};

template<TemplatedConfig<Annotated> auto v>
struct proc<v> {
    constexpr int foo() { return 1;}
};

// ... more config / specialization pairs ...

// Composite
template<typename... Parts>
struct Composite {
    std::tuple<Parts...> parts;
};

template<TemplatedConfig<Composite> auto v>
struct proc<v> {
    constexpr int foo() { return 2; }
};


int main() {
    constexpr Basic a = Basic{};
    constexpr Annotated b{a, 12};
    constexpr Composite c{std::make_tuple(a, b)};

    static_assert(proc<a>{}.foo() == 0);
    static_assert(proc<b>{}.foo() == 1);
    static_assert(proc<c>{}.foo() == 2);   <----- :(
}

Source: Windows Questions C++

LEAVE A COMMENT