Альтернативой шаблонам является использование лямбда-закрытия с C++ 11. Вот мои предпочтения.
// in header file
IClass * MyFunctionThatDoesStuff(const IParams & interface_params,
std::function<IClass * (const IParams & interface_params)> cls_allocator);
// in source file
IClass * MyFunctionThatDoesStuff(const IParams & interface_params,
std::function<IClass * (const IParams & interface_params)> cls_allocator) {
// Some processing. Perhaps the interface_params are generated
// inside this function instead of being passed to it.
IClass * mCls = cls_allocator(interface_params);
// Do whatever with mCls
return mCls;
}
// Somewhere else in the code.
{
Param1Type param1 = whatever1;
Param2Type param1 = whatever2;
// param1, param2, etc. are parameters that only
// SomeClsDerivedFromIClass constructor knows about. The syntax ¶m1
// achieves the closure.
// interface_param1 is common to all classes derived from IClass.
// Could more than one parameter. These parameters are parameters that
// vary from different calls of MyFunctionThatDoesStuff in different
// places.
auto cls_allocator =
[¶m1, ¶m2](const IParams & interface_params)->IClass * {
return new SomeCls1DerivedFromIClass(interface_params,
param1, param2);
};
IClass * mCls = MyFunctionThatDoesStuff(interface_params,
cls_allocator);
}
// Somewhere else in the code again.
{
ParamXType paramX = whateverX;
ParamYType paramY = whateverY;
auto cls_allocator =
[¶mX, ¶mY](const IParams & interface_params)->IClass * {
return new SomeCls2DerivedFromIClass(interface_params,
paramX, paramY);
};
IClass * mCls = MyFunctionThatDoesStuff(interface_params,
cls_allocator);
}
Вышеупомянутая идея кода хорошо подходит для быстрого построения шаблона или изменения заводского шаблона. Лямбда - это в основном заводский метод. Чтобы сделать его еще более динамичным, вы можете использовать auto для ввода параметров. Что-то вроде этого.
auto * MyFunctionThatDoesStuff(const auto & interface_params,
std::function<auto * (const auto & interface_params)> cls_allocator);
Я прихожу к этому из влияния Python, где вы можете просто передать тип класса функции.
@ Мартин, это интересное определение «относительно новое», учитывая, что Smalltalk, который был довольно мейнстримом в свое время и имел довольно много кода, написанных на нем, сделал именно это в 70-х годах :) –
Как и многие вещи, приписываемые Smalltalk, Lisp был там в 1950-х годах - вся программа была структурой данных, которую можно было проверять и манипулировать. –