Tobias Breuer
Tobias Breuer

Reputation: 875

Call template function from within a template class

GCC will not compile following code snippet (which in fact is correct behavior of GCC as it is conform to the standard C++ as I have learned already. VC++ however will compile.)

template<class T>
void CUDAMemory1D2DTextureAllocator<T>::allocateMemoryOnDevice()
{
    m_pChannelDesc = cudaCreateChannelDesc<T>();
    ...
}

As i already found out by searching is, that one needs to tell the compiler that cudaCreateChannelDesc is a template method. Otherwise it will try to parse < as a smaller than operator...

The following snippet shows that in an easy example:

template< typename G >
struct Test
{
    template< typename T > T f() const;
};

template< typename G, typename T >
void g()
{
    Test< G > t;

    t.f< T >();           // ERROR: gcc won't compile that
    t.template f< T >();  // OK: now gcc knows that f is a template method an treads the following angle brackets  not as operators but as template brackets...
} 

So far so good. Now my question is, how to do that in the above case, where the method I call is cudaCreateChannelDesc which does not belong to any class or namespace? Any advice or suggestion how to solve this situation are very welcome.

Thanks

Upvotes: 4

Views: 6679

Answers (3)

Mikael Persson
Mikael Persson

Reputation: 18572

I'm assuming that cudaCreateChannel1Desc is not a global or namespace function, because that should work, unless you forgot an include or a namespace resolution. And you do say it is a "method", i.e. a member function.

So, if it is a method of class CUDAMemory1D2DTextureAllocator, then you should use this->template cudaCreateChannel1Desc<T>() to call that method (which I have deduced is a method of a templated base class of CUDAMemory1D2DTextureAllocator. Below is a compact illustration of what works and what doesn't in different situations (at least on gcc):

template <class G>
struct Base {

  template< class T > 
  T h() const {
    std::cout << "Hello World!" << std::endl;
  };
};

template< class G >
struct Test : public Base<G>
{
    template< class T > 
    T f() const {
      std::cout << "Hello World!" << std::endl;
    };

    void callF() const {
      f<G>();                //works!
      this->f<G>();          //works!
      h<G>();                //ERROR!
      this->h<G>();          //ERROR!
      this->template h<G>(); //works!
    };
};

Upvotes: 2

Dan Paradox
Dan Paradox

Reputation: 1380

You can call it directly like: cudaCreateChannelDesc<T>() if it doesn't belong to any class or namespace. Isn't it working like that?

Upvotes: 2

Jeremiah Willcock
Jeremiah Willcock

Reputation: 30969

Is the cudaCreateChannelDesc function declared in some namespace that you have in scope? It appears that you might be having a problem with two-phase name lookup, which requires that some entities (like functions) referred to in templates need to be visible even before the template is instantiated. If you write a non-templated function in the same place as you definition of allocateMemoryOnDevice and call cudaCreateChannelDesc inside it, does the code compile? If not, you might be missing a #include or a namespace qualification on cudaCreateChannelDesc.

Upvotes: 1

Related Questions