I have a UIComponent class. Window, Button and Text inherit from it. UIComponent has a recursive structure in that it stores a std::vector<std::unique_ptr<UIComponent>> contents;. I am trying to write a function that recursively that goes through contents and finds the given UIComponent.
In my original code, I use a hash-table, but the following code very closely resembles what the original looks like (sorry if it's a bit long – I couldn't make it any shorter):
#include <vector>
#include <string>
#include <memory>
#include <iostream>
class UIComponent
{
public:
std::string name = "";
UIComponent() = default;
std::vector<std::unique_ptr<UIComponent>> contents;
UIComponent(const UIComponent& other) noexcept
{
for (auto& otherContent : other.contents)
{
contents.push_back(
std::make_unique<UIComponent>(*otherContent)//recursive call
);
}
}
template <
template <class> class Component,
class Fx
>
void Attach(const Component<Fx>& comp, std::string name)
{
contents.push_back(
std::move(std::make_unique<Component<Fx>>(comp))
);
contents.back()->name = name;
}
//Should search all the components and return one that matches
//the argument
UIComponent* GetComponent(const std::string& name)
{
static UIComponent* pOut = nullptr;
for (size_t i = 0; i < contents.size(); i++)
{
if (name == contents[i]->name)
{
pOut = contents[i].get();
return pOut;
}
}
if (pOut != nullptr)
{
return pOut;
}
for (auto& content : contents)
{
content->GetComponent(name);
}
return pOut;
}
};
template < class Fx >
class Window : public UIComponent
{
public:
Window() = default;
};
template < class Fx >
class Button : public UIComponent
{
public:
Button() = default;
};
template < class Fx >
class Text : public UIComponent
{
public:
Text() = default;
};
Window<void(void)> window;
Button<void(void)> button;
Text<void(void)> text;
int main()
{
window.Attach<Button, void(void)>(button, "button");
button.Attach<Text, void(void)>(text, "text");
auto b = window.GetComponent("button");
if (b != nullptr)
{
std::cout << b->name << " : " << typeid(*b).name() << '\n';
}
auto t = window.GetComponent("text");
if (t != nullptr)
{
std::cout << t->name << " : " << typeid(*t).name() << '\n';
}
}
Actual Output:
button : class UIComponent
button : class UIComponent
Expected output:
button : class Button<void(void)>
text : Text<void(void)>
The function I am struggling with is UIComponent* GetComponent(const std::string& name).
It always returns a UIComponent*. I am not sure how to make it so that tt returns the correct child class type. I am also not sure about the logic but that might not be strictly related to the question.