lurscher
lurscher

Reputation: 26943

forward declarations, and template instantiation context

I have a header that forward declares a struct, a function, and defines a template function that uses the struct concrete type:

---header.h

struct RegisterImpl;
RegisterImpl& getRegisterImpl();

template <typename Interface>
void registerModuleClass( .... )
{
  RegisterImpl& reg = getRegisterImpl();
  reg.data = 3;
  ...
}

---source.cpp

struct RegisterImpl
{
  int data;
};

RegisterImpl& getRegisterImpl()
{
  static RegisterImpl instance;
  return instance;
}

struct testiFace
{
   virtual void Blah() = 0;
};

void useTemplate()
{
   registerModuleClass<testiFace>(....);
}

my hope was that instantiation of template function registerModuleClass was going to happen at useTemplate, which happens after the RegisterImpl type is fully defined. But it seems that type resolution of the code is happening at the place where the template definition exists, instead of the instantiation (at the source file)

Am i missing something here? The dilemma here is that the template function needs to use the concrete type of the implementation, but the concrete type happens in the source file. Any way around this?

Upvotes: 1

Views: 561

Answers (2)

Daniel Frey
Daniel Frey

Reputation: 56863

Make it depend on the template parameter(s):

template<typename T, typename...> struct depend { typedef T type; };

template <typename Interface>
void registerModuleClass( .... )
{
  typedef typename depend<RegisterImpl,Interface>::type LocalRegisterImpl;
  LocalRegisterImpl& reg = getRegisterImpl();
  reg.data = 3;
  ...
}

Upvotes: 0

StackedCrooked
StackedCrooked

Reputation: 35485

I'm not sure if this suggestion will help in your situation, but here is an idea: you could wrap the code in a class template that requires RegisterImpl as a template parameter.

Example:

template<typename T>
struct Helper
{
    T & getRegisterImpl()
    {
        static T instance;
        return instance;
    }

    template<typename Interface>
    void registerModuleClass()
    {
        T & reg = getRegisterImpl();
    }
};

And later:

struct RegisterImpl
{
    int data;
};

Helper<RegisterImpl> helper;

I hope this helps.

Upvotes: 1

Related Questions