Advertisement

"No match for call to" error, help please

Started by October 20, 2015 03:36 AM
11 comments, last by jpetrie 9 years, 2 months ago

Hi,

So I've been trying to compile this code, but it always results in an error:


menuhandler.cpp|18|error: no match for call to '(std::vector<GuiElem>) (Button)'|

I was trying to create a simple menu system...

Here's the code:

menuhandler.hpp


#pragma once

class GuiElem
{
    public:
        static std::vector<GuiElem> guiElems;
        float PosX;
        float PosY;
        float Width;
        float Height;
        float Rot;

        bool SetPos(float newX, float newY);
        bool SetWidth(float newWidth);
        bool SetHeight(float newHeight);
        bool SetRot(float newRot);
};

class Button : public GuiElem
{
    public:
        sf::String textDisplay;

        Button(sf::String name, float x, float y, float width, float height);
        bool newButton(sf::String name, float x, float y, float width, float height);
        bool isClicked();
        bool isMouseIn();
};

menuhandler.cpp


#include <SFML/Graphics.hpp>
#include <vector>
#include "menuhandler.hpp"

Button::Button(sf::String name, float x, float y, float width, float height)
{
    textDisplay = name;
    PosX = x;
    PosY = y;
    Width = width;
    Height = height;
}

bool Button::newButton(sf::String name, float x, float y, float width, float height)
{
    try
    {
        GuiElem::guiElems(Button(name, x, y, width, height));
        return true;
    }
    catch(...)
    {
        return false;
    }
}

Thanks in advance...

When you use the syntax someObject(parameters), the compiler checks to see if the type of someObject declares a call operator, that is, a function that is invoked when using function call syntax on the object itself. That's what is happening with GuiElem::guiElems(Button(...)). GuiElem::guiElems is an object, and Button(...) is a temporary object that is interpreted as a parameter.

But std::vector<> does not declare a call operator, so the compiler doesn't know what you're trying to do. As a human, I can speculate that you're trying to add the new button to the container of GUI elements. And since std::vector<>'s most natural insertion function is push_back(), I can guess that you want to add the new button to the end of the vector. In which case you'd want to call GuiElem::guiElems.push_back(Button(...)). Alternatively, if you're using C++11, you can make the construction of the new button implicit by using emplace_back: GuiElem::guiElems.emplace_back(name, x, y, width, height). This will simply forward the parameters onto the constructor of the container's element type that best matches the parameters.

I'll add a quick note that your use of static member fields strikes my architect's nose as an immediate code smell, suggesting that your design of handling GUI element lifetime/ownership is probably less than ideal. But that's a separate issue, so I'll won't delve into it here. But it's something to keep in the back of your mind as you extend your framework.

"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
Advertisement

Thanks dude :D, I don't get that error anymore, tho I get a new error:


undefined reference to `GuiElem::guiElems

I have no idea why that error shows up. Help please?

if you declare a member as static, you must also define it in your cpp-file, or there will be no instance of the member created.

So in your cpp-code you will need a line like this somewhere:

std::vector<GuiElem> GuiElem::guiElems;

BUT!

There is another huge problem with your code that will come back and bite you.

You can not assign subclasses to an array of superclasses, if you do, your objects will be sliced and your program will not behave as you expect.

If you need polymorphism, you need to store pointers to the classes in the array.

There is another huge problem with your code that will come back and bite you.

You can not assign subclasses to an array of superclasses, if you do, your objects will be sliced and your program will not behave as you expect.

If you need polymorphism, you need to store pointers to the classes in the array.

So how would I fix that problem? :S

Olof Hedman already said so: you need to store pointers, like for examples this:


#include <memory>
// ...
std::vector<std::unique_ptr<GuiElem>> guiElems;
// ...
guiElems.push_back(std::make_unique<Button>(...)); // requires a C++14-capable compiler
guiElems.push_back(std::unique_ptr<Button>(new Button(...))); // does not require a C++14-capable compiler
Advertisement
guiElems.push_back(std::make_shared<Button>(...)); // requires a C++14-capable compiler

Did you mean to call make_unique?
Yes. I would edit it to correct it, unfortunately the editor in this browser would mangle the whole post in the process.

I fixed it with mod hacks.

guiElems.push_back(std::unique_ptr(new Button(...)));

Since "new" has been used, should I also use "delete" after?

This topic is closed to new replies.

Advertisement