Alright, first things first, I will be providing the code I am asking my question for.
EX_Factory.h
#ifndef EX_FACTORY_H
#define EX_FACTORY_H
#include <string>
#include <map>
#include "Base.h"
struct EX_Factory{
template<class U, typename... Args>
static void registerC(const std::string &name){
registry<Args...>[name] = &create<U>;
}
template<typename... Args>
static Base * createObject(const std::string &key, Args... args){
auto it = registry<Args...>.find(key);
if(it == registry<Args...>.end()) return nullptr;
return it->second(args...);
}
private:
EX_Factory() = delete;
template<typename... Args>
static std::map<std::string, Base*(*)(Args...)> registry;
template<class U, typename... Args>
static Base* create(Args... args){
return new U(args...);
}
};
template<typename... Args>
std::map<std::string, Base*(*)(Args...)> EX_Factory::registry;
template<typename U, typename... Args>
struct MiddleMan{
MiddleMan(const std::string &name){
EX_Factory::registerC<U,Args...>(name);
}
};
#define REGISTER_MACRO(NAME, TYPE, ...)\ // Updated the macro here
static MiddleMan<TYPE, ##__VA_ARGS__> mm_##TYPE(#NAME);
#endif
The code above is a header file for my Factory Design Pattern class. It allows the user of this class to register constructors for objects derived from the Base class with varying arguments.
Alright, quick explanation for why I am using __VA_ARGS__ vs ##__VA_ARGS__, the reason for this is, there will always be at least 1 argument, the template type U in the registerC template function, passed into the macro.
What I am trying to do is construct a preprocessor macro, REGISTER_MACRO , to register derived classes before runtime. How do I call a Variadic Template Function from a Variadic Macro correctly?
Tests or main.cpp
#include "EX_Factory_1.h"
#include <iostream>
using namespace std;
struct derived_1 : public Base{
derived_1(int i, int j, float f){
cout << "Derived 1:\t" << i * j + f << endl;
}
};
REGISTER_MACRO(name_1, derived_1, int,int,float);
struct derived_2 : public Base{
derived_2(int i, int j){
cout << "Derived 2:\t" << i + j << endl;
}
};
REGISTER_MACRO(name_2, derived_2, int,int);
int main(){ // Program segfaults before entering main
derived_1 * d_1 = static_cast<derived_1*>(EX_Factory::createObject<int, int, float>("name_1", 8, 8, 3.0));
if(d_1 == nullptr) cout << "Why is it null?" << endl;
else{
delete d_1;
}
return 0;
}
The errors I am receiving from trying to compile the above code: See Edit below
In file included from test.cpp:1:0:
EX_Factory.h:39:38: error: expected constructor, destructor, or type conversion before ‘(’ token
EX_Factory::registerC<__VA_ARGS__>(NAME);
^
test.cpp:11:1: note: in expansion of macro ‘REGISTER_MACRO’
REGISTER_MACRO("derived_1",derived_1,int,int,float)
^~~~~~~~~~~~~~
EX_Factory.h:39:38: error: expected constructor, destructor, or type conversion before ‘(’ token
EX_Factory::registerC<__VA_ARGS__>(NAME);
^
test.cpp:17:1: note: in expansion of macro ‘REGISTER_MACRO’
REGISTER_MACRO("derived_2",derived_2,int,int)
I am using the g++ 6.3 compiler, so by default, it compiles with C++14 standards in an Ubuntu 16.04 environment.
Potential solutions I've found, but don't fit my problem:
Is there a way to define variadic template macro
Using variadic macros or templates to implement a set of functions
Potential Solution but could not interpret its solution:
How to use variadic template with variadic macro ? I'm not using QT, and I am using a fully supported C++11 compiler.
Edit
I now know why my file will not compile, but I do not know how to handle creating an object to call the method for myself. I added a middle man class, MiddleMan, and added a call to the static registerC class to its constructor and modified my macro to create static references to this class. This allows my program to compile, but it segfaults with this method. You will see the mentioned reflections above now.
I am testing this class and macro out with my main.cpp in my answer to this question.