С++ Помогите избавиться от дублирования однотипного кода.
Всем доброго времени суток. Возникла проблема (точнее, понимание того, что в одном месте код фактически N раз дублируется). Приведенный далее код просто поясняет проблему и даже не компилировался.
Дано: 1. Интерфейсный класс с тремя (на самом деле, их значительно больше) методами разных сигнатур.
// Интерфейсный класс родителя.
class IParent
{
public:
virtual bool fu0() = 0;
virtual bool fu1(const std::string &) = 0;
virtual std::string fu2() = 0;
virtual ~IParent() = 0;
};
2. Потомки с конкретными реализациями этих методов. Понятно, что потомков может быть сколько угодно.
class CChild0 : public IParent
{
public:
virtual bool fu0() override
{
// Что-то делаем.
}
virtual bool fu1(const std::string & param) override
{
// Опять что-то много делаем.
}
virtual std::string fu2() override
{
// И тут делаем.
}
};
3. Супер-класс, который хранит в себе через указатели на базовый класс потомков в мапе.
class CSuperHandler
{
private:
// Мапа для хранения потомков через указатель на родителя. Ключ - далее id.
std::map<int, std::unique_ptr<IParent>> mMap;
public:
CSuperHandler()
{
//Заполнение мапы может быть не только тут.
mMap.insert(std::make_pair(0, std::unique_ptr<IParent>(new CChild0)));
mMap.insert(std::make_pair(1, std::unique_ptr<IParent>(new CChild1)));
mMap.insert(std::make_pair(2, std::unique_ptr<IParent>(new CChild2)));
}
// Должен запускать метод fu0 если найден потомок.
bool SuperFu0(const int id)
{
auto it = mMap.find(id);
bool returnValue = false;
if(it != mMap.end())
{
returnValue = it->second->fu0();
}
else
{
std::cout << "ID not found.";
}
return returnValue;
}
// Должен запускать метод fu1 если найден потомок.
bool SuperFu1(const int id, const std::string & param)
{
auto it = mMap.find(id);
bool returnValue = false;
if(it != mMap.end())
{
returnValue = it->second->fu1(param);
}
else
{
std::cout << "ID not found.";
}
return returnValue;
}
// Должен запускать метод fu2 если найден потомок.
std::string SuperFu2(const int id)
{
auto it = mMap.find(id);
std::string returnValue = "";
if(it != mMap.end())
{
returnValue = it->second->fu2();
}
else
{
std::cout << "ID not found.";
}
return returnValue;
}
};
Собственно, что проблема в том, что методы SuperFu0, SuperFu1,SuperFu2 (а на самом деле, их много) имеют практически одинаковое содержимое: проверяют есть ли нужный id и запускают у соотвествующего потомка метод, результат которого возвращают. Пока я не придумал как можно это дело оптимизировать.
Хотелось бы, конечно, иметь что-то вроде:
template<typename T, typename... Args>
T doAction(int id, std::function<T(const Args & ... args)> fu, const Args & ... args)
{
auto it = mMap.find(id);
T returnValue;
if(it != mMap.end())
{
returnValue = it->second->fu(args...);
}
else
{
std::cout << "ID not found.";
}
return returnValue;
}
Но мы же не можем передать туда указатель на метод объекта, которого при вызове шаблонного метода еще не знаем (он внутри по id определяется). В общем, если кто-то подскажет какое-то удачное решение - буду очень рад. Спасибо!