views:

182

answers:

1

I have a class factory where I'm using variadic templates for the c'tor parameters (code below). However, when I attempt to use it, I get compile errors; when I originally wrote it without parameters, it worked fine.

Here is the class:

template< class Base, typename KeyType, class... Args >
class GenericFactory
{
public:
   GenericFactory(const GenericFactory&) = delete;
   GenericFactory &operator=(const GenericFactory&) = delete;

   typedef Base* (*FactFunType)(Args...);

   template <class Derived>
   static void Register(const KeyType &key, FactFunType fn)
   {
      FnList[key] = fn;
   }

   static Base* Create(const KeyType &key, Args... args)
   {
      auto iter = FnList.find(key);
      if (iter == FnList.end())
         return 0;
      else
         return (iter->second)(args...);
   }

   static GenericFactory &Instance() { static GenericFactory gf; return gf; }
private:
   GenericFactory() = default;

   typedef std::unordered_map<KeyType, FactFunType> FnMap;
   static FnMap FnList;
};

template <class B, class D, typename KeyType, class... Args>
class RegisterClass
{
public:
   RegisterClass(const KeyType &key)
   {
      GenericFactory<B, KeyType, Args...>::Instance().Register(key, FactFn);
   }
   static B *FactFn(Args... args)
   {
      return new D(args...);
   }
};

Here is the error: when calling (e.g.)

// Tucked out of the way
RegisterClass<DataMap, PDColumnMap, int, void *> RC_CT_PD(0);

GCC 4.5.0 gives me:

In constructor 'RegisterClass<B, D, KeyType, Args>::RegisterClass(const KeyType&) [with B = DataMap, D = PDColumnMap, KeyType = int, Args = {void*}]':
no matching function for call to 'GenericFactory<DataMap, int, void*>::Register(const int&, DataMap* (&)(void*))'

I can't see why it won't compile and after extensive googling I couldn't find the answer. Can anyone tell me what I'm doing wrong (aside from the strange variable name, which makes sense in context)?

+1  A: 

I think it's barfing here:

template <class Derived> 
static void Register(const KeyType &key, FactFunType fn) 
{ 
   FnList[key] = fn; 
} 

You don't use Derived in this function, but it's probably messing up gcc's attempt to resolve GenericFactory<...>.Register(...). You might also want to change that to GenericFactory<...>::Register(...).

MSN
Thanks, that worked. I knew it had to be something simple!