Reputation: 164
I'm setting up a function that initializes tuples based on a tuple type and a functor struct For
that has a size_t template argument INDEX
to retain the compile-time index. This functor may also depend on other template arguments T...
. Because of this the functors exist within other structures (TClass
in this example) that hold these template arguments.
The initialization function (called Bar
here) has a template<std::size_t> class
template argument to ensure that the used class actually can store the index.
While the design I've come up with works fine when I call it from a non-template function, it does not compile if the template T2
of a function does determine the template parameter of the wrapper TClass
.
Here is the definition of the functor For
wrapped inside TClass
:
#include <cstdlib>
template <typename T> struct TClass {
template<std::size_t INDEX> struct For {
void operator()() {}
};
};
And here are the function calls i want to use:
template <template<std::size_t> class FOR> void bar() {
//...
}
template <typename T> void foo() {
bar<TClass<T>::For>(); //Does not compile
}
int main() {
bar<TClass<int>::For>(); //Works
foo<int>();
return 0;
}
The compiler output for the faulty foo
-call is:
error: dependent-name ‘TClass<T>::For’ is parsed as a non-type, but instantiation yields a type
Bar<TClass<T>::For>(); //Does not compile
I know that dependent type names usually have to be preceded by a typename
but this is also not necessary for the first bar
-call. I assumed it was because the template argument can only be interpreted as a type. So I thought that maybe typename
would result in correct compilation but if I change foo
to
template <typename T> void foo() {
bar<typename TClass<T>::For>(); //Does not compile
}
I get:
error: ‘typename TClass<int>::For’ names ‘template<long unsigned int INDEX> struct TClass<int>::For’, which is not a type
Bar<typename TClass<T>::For>(); //Does not compile
I've also come up with a design where the ()
-operator of TClass
depends on the template INDEX
which also works fine because it is not necessary to use nested types anymore. It looks like this:
#include <cstdlib>
template <typename T> struct TClass {
template<std::size_t INDEX> void operator()() {}
};
template <typename FOR> void bar() {
//...
}
template <typename T> void foo() {
bar<TClass<T>>(); //Does compile
}
Apparently it is not possible to use dependent type names in functions where the template of the type is determined by the function's template parameters, but why? And how do I implement this correctly? To make writing future type checks with type traits easier I would prefer it if I can use a functor.
Upvotes: 4
Views: 230
Reputation: 136266
The compiler cannot know that TClass<T>::For
refers to a template at the first stage of template instantiation. It needs a bit of help with template
keyword. Fix:
template <typename T> void foo() {
bar<TClass<T>::template For>();
}
Upvotes: 4