Reputation: 22084
I have to create many business objects (Each client should get it's own class). Ideally I would like to be able to access the class by the clients internal tag i.e. Client::getName(void)
, so I created a macro which achieves this.
#define CLIENT_CLASS(classname) \
class classname : public Base \
{ \
public: \
classname(void); \
~classname(void) {}; \
public: \
static const std::string name; \
static ClientId ID(void) { return CID_##classname; } \
static Base *createInstance(void) { return new classname(); } \
private: \
typedef Base super; \
}
Originally I copied this as each class seperately, but naturally I'd like to have something that can be edited if need be. I would have preferred to implement this as a template, but I'm not sure if this is even possible, because I don't see any way to specify the classname in a template and AFAIK you can not define static methods in a template anyway? Or am I wrong and there is indeed a way to convert this into a proper template?
CLIENT_CLASS_BODY
is another macro which bascially looks like the other one, but contains the definition of the common class body (which could be moved to the template if it is possible to templatize it).
The factory looks like this:
namespace va {
CLIENT_CLASS(client1);
CLIENT_CLASS(client2);
....
}
namespace va {
CLIENT_CLASS_BODY(client1);
CLIENT_CLASS_BODY(client2);
...
}
#define CREATE_CLIENT(classname) addKey(classname::name, classname::ID(), classname::createInstance())
void ClientFactory::initClientMap(void)
{
CREATE_CLIENT(va::client1);
CREATE_CLIENT(va::client2);
...
}
Upvotes: 1
Views: 2199
Reputation: 217293
With template, it should look like something like:
template <ClientId Id, const char* Name>
class TClient : public Base
{
public:
TClient() {}
~TClient() {}
public:
static const std::string name;
static ClientId ID() { return Id; }
static Base *createInstance() { return new TClient(); }
private:
using super = Base;
};
template<ClientId Id, const char* Name> const std::string TClient<Id, Name>::name = Name;
And then
static constexpr char Client1Name[] = "Client1";
using Client1 = TClient<1, Client1Name>;
In the same way,
#define CREATE_CLIENT(classname) addKey(classname::name, classname::ID(), classname::createInstance())
should be
template <typename T>
void ClientFactory::CreateClient()
{
addKey(T::name, T::ID(), T::createInstance());
}
and then
void ClientFactory::initClientMap()
{
CreateClient<va::client1>();
CreateClient<va::client2>();
//...
}
Upvotes: 2