This is a tricky area of C++. What you've done is to try to define the static member here:
template<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper;
but this is actually a declaration and not a definition. For C++ to treat it as a definition you have to pass something to the constructor. Typically, this is the value you want to initialize it to:
template<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper = FactoryHelper<ClassName##Factory>();
But in your case, you want this to be a singleton, so you probably don't want it to be copyable. In that case, you need some dummy parameter:
template<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper(0);
and you have to modify your constructor appropriately:
template<> FactoryHelper<ClassName##Factory>::FactoryHelper (int) { std::cout << "object initialized!" << std::endl; }
Here is the complete working example:
#include <iostream>
namespace my_lib
{
template<typename> struct FactoryBase { };
template <typename T>
struct FactoryHelper
{
FactoryHelper (int);
static FactoryHelper<T> _helper;
};
}
#define CREATE_FACTORY(ClassName)
namespace my_lib
{
class ClassName##Factory;
template<> FactoryHelper<ClassName##Factory>::FactoryHelper (int) { std::cout << "object initialized!" << std::endl; }
template<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper(0);
struct ClassName##Factory : public FactoryBase<ClassName> {
};
}
struct UnitTestExample {
};
CREATE_FACTORY(UnitTestExample);
int main(int argc,char **argv)
{
return 0;
}
That said, using some of the suggestions in the other answers may be a better design decision.
More information on the explicit specialization declaration vs. definition can be found here: static member initialization for specialized template class
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…