Reputation: 1970
I am trying to pass an inner template class (of a regular class) to another class that accepts templates as arguments.
The class that accepts templates is:
template <typename... T> struct TypeList {
template <template <typename...> typename P> using Apply = P<T...>;
};
So when I have something like using List = TypeList<int, float, double>;
I can do
static_assert(std::is_same<List::template Apply<std::tuple>,
std::tuple<int, float, double>>::value);
But if I change std::tuple
so an inner template class, it stops working. I.e.,
struct Outer {
template <typename... P> struct Inner {};
};
static_assert(std::is_same<List::template Apply<typename Outer::Inner>,
Outer::Inner<int, float, double>>::value);
doesn't work.
My compiler complains about
error: invalid use of template-name ‘Outer::Inner’ without an argument list
It works if I "flatten" the inner template class with template <typename... P> using Flat = Outer::Inner<P...>;
.
My question is, is there a way to make the inner template class work, without aliasing it and flattening it? Am I missing the typename
or template
keyword somewhere?
Complete example is:
#include <tuple>
#include <type_traits>
template <typename... T> struct TypeList {
template <template <typename...> typename P> using Apply = P<T...>;
};
struct Outer {
template <typename... P> struct Inner {};
};
template <typename... P> using Flat = Outer::Inner<P...>;
int main() {
using List = TypeList<int, float, double>;
static_assert(std::is_same<List::template Apply<std::tuple>,
std::tuple<int, float, double>>::value);
static_assert(std::is_same<List::template Apply<Flat>,
Outer::Inner<int, float, double>>::value);
static_assert(std::is_same<List::template Apply<typename Outer::Inner>,
Outer::Inner<int, float, double>>::value);
}
Upvotes: 1
Views: 192
Reputation: 217135
typename Outer::Inner
is wrong as Inner
is not a type but a template.
You can even remove all typename/template here as there is no dependent type issue.
static_assert(std::is_same<List::Apply<Outer::Inner>,
Outer::Inner<int, float, double>>::value);
In dependent context, it would be
// template <typename OuterT> /*..*/
static_assert(std::is_same<List::Apply<OuterT::template Inner>,
typename OuterT::template Inner<int, float, double>>::value);
Upvotes: 2