Convert panels and childwindows to containers

Started by starkhorn, 09 June 2015, 00:44:33

starkhorn

So I've a vector of panels and also a vector of childwindows

Code (cpp) Select

vector<tgui::Panel::Ptr> PanelList;
vector<tgui::ChildWindow::Ptr> childWindowList;


I have a function that wants to check if a panel or child window is already present in either vector. I use the get widgetname function.

Code (cpp) Select

bool drawEngine::isWidgetPresentInContainer(string passed_widgetName, vector<tgui::Container::Ptr> containerList)
{
string retrievedWidgetName;

for (int i=0; i < containerList.size(); i++)
{
if (gui.getWidgetName(containerList[i], retrievedWidgetName))
{
if (retrievedWidgetName == passed_widgetName)
{
return true;
}
}
}
return false;
}


Now as you can see I've defined the parameter in the function as  vector<tgui::Container::Ptr>.
As both panels and childwindows inherit from this class and the method of getWidgetName is within the container class then I kinda hoped that I could write one function regardless whether the vector is a panel or a child window.

However obviously when I call it I get

Code (cpp) Select

215 IntelliSense: no suitable user-defined conversion from "std::vector<tgui::ChildWindow::Ptr, std::allocator<tgui::ChildWindow::Ptr>>" to "tgui::Container::Ptr" exists


Is there any way to do this ?

starkhorn

#1
I should add, that if I remove the vector and try to pass in a single childwindow or panel into the function, as below there is no issue.

So I'm assuming that this is actually a std::vector issue?

Code (cpp) Select


bool drawEngine::IsPanelAlreadyInPanelList(string passed_widgetName)
{
bool returnVal = false;

    for (int i = 0; i < PanelList.size(); i++)
    {
returnVal = isWidgetPresentInContainer(passed_widgetName, PanelList[i]);
    }

return returnVal;
}

bool drawEngine::IsChildWinAlreadyInChildList(string passed_widgetName)
{
bool returnVal = false;

    for (int i = 0; i < childWindowList.size(); i++)
    {
returnVal = isWidgetPresentInContainer(passed_widgetName, childWindowList[i]);
    }

return returnVal;
}

bool drawEngine::isWidgetPresentInContainer(string passed_widgetName, tgui::Container::Ptr container)
{
string retrievedWidgetName;

if (gui.getWidgetName(container, retrievedWidgetName))
{
if (retrievedWidgetName == passed_widgetName)
{
return true;
}
}
return false;
}


texus

#2
I can think of two ways to handle this, both with their own advantages and disadvantages.

The first one is to use a vector<tgui::Widget::Ptr> everywhere, so both PanelList and childWindowList would be of that type. This of course has the disadvantage that if you want to call function that are specific to Panel or ChildWindow you would first have to cast the pointer every time to call that function.

The second option looks better to me: templates. They are made exactly for situations like this where you need the same code for different types. It even has the advantage that the code not only works for Panel and ChildWindow but for every type of widget. The minor downside is that you will need to put the function definition in a header if you want to use it from multiple files. And although you only have to write one function definition. Inside the class definition in the header file you would write the following:
Code (cpp) Select
template <typename T> bool isWidgetPresentInContainer(string passed_widgetName, vector<typename T::Ptr> containerList) { /* ... */ }

There might be a third option though. But that involves asking yourself if a function like this is the best way. I can't answer that because it depends too much on the situation. Other options would be to store a vector of pairs with the pointer and its name, or even store two vectors. That way you have both a list of pointers and a list of names, this function would just be replaced by a find call on the second vector (or for the second attribute in the pair).

Edit:
QuoteSo I'm assuming that this is actually a std::vector issue?
This isn't really an "issue", both vectors are of a completely different type as far as the compiler is concerned. I know that it would be nice if it would just accept that both version just are similar to a vector of pointers of any type, but that is not how c++ works. C++ is statically typed which leads to these vectors being incompatible. Its just a limitation of the language.

starkhorn

Hi Texus,

Ok thanks for the response. I've not used template before so this looks like a good time to start... :)