I was playing around with templates, and ended up with a code like this:
#include <iostream>
#include <tuple>
#include <functional>
template<int... seq>
class A {
public:
template<int... s>
inline constexpr auto foo() const noexcept {
return A<(std::get<s>(std::forward_as_tuple(seq...)))...>();
}
};
template<int... seq>
class B {
public:
template<int... s>
inline constexpr auto foo() const noexcept {
return B<(std::get<s>(std::forward_as_tuple(seq...)))...>();
}
};
template<class A, class B>
class C {
public:
template<int... s>
inline constexpr auto bar() const noexcept {
// I tried all of the following:
constexpr A a;
a.foo<s...>(); // error: parameter pack not expanded with ...
return C<decltype(std::declval<A>().foo()), decltype(std::declval<B>().foo())>(); // works but no parameters are passed
return C<decltype(std::declval<A>().foo<s...>()), decltype(std::declval<B>().foo<s...>())>(); // doesn't work
return C<decltype(std::invoke(std::declval<A>().foo(), s...)), decltype(std::invoke(std::declval<B>().foo(), s...))>(); // doesn't work
}
};
// I get the types of the objects, but I can't instantiate them
// because I don't have the parameters needed to create the object
template<template<int...> class A, template<int...> class B>
class D{};
// Similar attempt to D
// Not working because the parameter pack has to be at the end of the template parameter list
// But at the same time, I need two parameter packs
template<template<int...> class A, int... e1, template<int...> class B, int... e2>
class E {};
int main() {
constexpr C<A<1, 2, 3>, B<4, 5, 6>> c;
c.bar<2, 1, 0>();
return 0;
}
Ideally, I'd like to get class C working, so that I can call the method bar with parameters as I'm passing them now, and somehow delegate them to the calls A::foo and B::foo, but I can't figure out what's going wrong exactly.
Does anyone know how could I achieve this? Or how can I do anything similar to it? I'm using C++17, and I need all of the objects evaluated at compile-time