Stefan Groth
Stefan Groth

Reputation: 164

How can I use a nested type belonging to a templated class in another template function in C++?

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

Answers (1)

Maxim Egorushkin
Maxim Egorushkin

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

Related Questions