Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: [Résolu][Threads] Too many arguments to function  (Lu 2101 fois)

0 Membres et 1 Invité sur ce sujet

Glân de Brylan

  • Jr. Member
  • **
  • Messages: 83
  • Je pense ce que je dis et le dis comme je le pense
    • Voir le profil
[Résolu][Threads] Too many arguments to function
« le: Septembre 24, 2014, 09:36:01 am »
EDIT :
J'ai trouvé. Button.cpp, ligne 34 : chkClicked=new sf::Thread(newFunc, parent);
Par contre, je ne vois pas en quoi j'ai donné trop d'arguments...

Bonjour,
Je suis bloqué sur une erreur que je ne comprends pas :
SFML-2.1\include\SFML\System\Thread.inl  ||  In instantiation of 'void sf::priv::ThreadFunctorWithArg<F, A>::run() [with F = void (*)(); A = MWindow*]':
Button.cpp  |145|  required from here
SFML-2.1\include\SFML\System\Thread.inl  |48|  error: too many arguments to function

MWindow.h :
#ifndef MWINDOW_H
#define MWINDOW_H


#include <SFML/Graphics.hpp>

#include <vector>


class MWindow;

class Button : public sf::Sprite
{
    friend class MWindow;
    public:
        Button(std::string const& adress, std::string const& adressO=std::string(), std::string const& adressL=std::string(), std::string const& adressD=std::string());

        virtual ~Button();

        bool setParent(MWindow *newParent = nullptr, void (*newFunc)() = nullptr);
        // Sets 'parent' to newParent. If newParent is null, the button is disabled and ID is set to -1. Else it is enabled.
        // Returns true if the parent has been successfully changed, else false.

        MWindow* getParent();
        // Returns 'parent' member.

        virtual void setEnabled(bool yay);
        // Sets the 'enabled' value to yay and changes de texture in consequences. An hidden button cannot be enabled.

        bool getEnabled();
        // Returns the 'enabled' member value

        virtual void setHidden(bool hide);
        // Sets the 'hidden' member to hide. If true, texture is set to 'texture', else to an empty texture.
        // An hidden button is also disabled. Unhidde a button automatically re-enables it.

        bool getHidden();
        // Returns the 'hidden' member value

        void changeTexture(std::string const& adress);
        // texture.loadFromFile(adress);

        void changeTextureOver(std::string const& adress=std::string());
        // Give it an empty string and  textureOver will be set with 'texture'
        void changeTextureLeaned(std::string const& adress=std::string());
        // Give it an empty string and  textureLeaned will be set with 'texture'
        void changeTextureDisabled(std::string const& adress=std::string());
        // Give it an empty string and  textureDisabled will be set with 'texture'

    protected:
        void checkClicked();
        // Uses the sf::Event event to verify if the mouse is over the button and if the user clicks on

        MWindow *parent;
        sf::Texture texture, textureOver, textureLeaned, textureDisabled;
        sf::Thread *chkClicked;
        bool enabled, mouseOver, leaned, hidden;
        int ID;
};



/////////////////////////////////////// MWindow ///////////////////////////////////////

class MWindow
{
    friend class Button;
    public:
        MWindow(int x = 800, int y = 600, std::string const& title = "Main Window", bool deletebuttons = true, sf::ContextSettings const& settings = sf::ContextSettings());
        /* Arguments :
         * 'title' is simply the title of the window.
         * 'deletebuttons' : if true, the buttons in the vector 'buttons' will be deleted in the destructor.
         * 'x' ans 'y' are respectively the width and the height of the window
        */


        MWindow(sf::RenderWindow *windowPtr, bool deletebuttons = true);

        virtual ~MWindow();

        virtual void startEventLoop();

        bool addButton(Button *button, void (*func)());
        // Returns true if the button is successfully added, false if the button was already in the window

        bool removeButton(Button *button);
        // Returns true if the button is successfully removed from the window, false if the button was not in the window.
        // Note that this function does NOT delete the button.

        bool removeButton(int index);
        // Overload of removeButton(). Remove the Button at the 'index' position. Return true if successful, false if the 'index' position does not exist.
    protected:
        virtual void update();
        // clear-draw-display function

        virtual void checkButtons();
        // checks if

        sf::RenderWindow *window;
        sf::Thread checkBtns;
        std::vector<Button*> buttons;
        std::vector<void (*)()> functions;
        bool deleteButtons;
        sf::Event event;
};

#endif // MWINDOW_H
 

MWindow.cpp :
#include "MWindow.h"

MWindow::MWindow(int x, int y, std::string const& title, bool deletebuttons, ContextSettings const& settings) : \
    window(new sf::RenderWindow(sf::VideoMode(x,y), title, sf::Style::Titlebar | sf::Style::Close, settings)), \
    checkBtns(&MWindow::checkButtons, this), buttons(), deleteButtons(deletebuttons)
{
    checkBtns.launch();
}

MWindow::MWindow(sf::RenderWindow *windowPtr, bool deletebuttons) : window(windowPtr), checkBtns(&MWindow::checkButtons, this), buttons(), deleteButtons(deletebuttons)
{
    checkBtns.launch();
}

MWindow::~MWindow()
{
    if(deleteButtons)
    {
        for(int i(0) ; i < (int)buttons.size() ; i++)
            delete buttons[i];
    }
    else
    {
        for(int i(0) ; i < (int)buttons.size() ; i++)
            if(buttons[i] != nullptr)
                buttons[i].ID=-1;
    }
}

MWindow& MWindow::operator=(const MWindow& rhs)
{
    if (this == &rhs) return *this; // handle self assignment
    //assignment operator
    return *this;
}

void MWindow::startEventLoop()
{
    while(window->isOpen())
    {
        update();
        while(window->pollEvent(event))
        {
            if(event.type == sf::Event::MouseButtonPressed || event.type == sf::Event::MouseButtonReleased || event.type == sf::Event::MouseMoved)
            {
                for(int i(0) ; i < (int)buttons.size() ; i++)
                    if(buttons[i] != nullptr && buttons[i]->getEnabled())
                        buttons[i]->checkClicked(event);
            }
        }
    }
}


bool MWindow::addButton(Button *button, void (*func)())
{
    for(int i(0) ; i < (int)buttons.size() ; i++)
        if(buttons[i] == button)
            return false;

    if(buttons.empty())
    {
        buttons.push_back(button);
        button->ID=0;
        functions.push_back(func);
        return;
    }
    for(int i(0) ; i < (int)buttons.size() ; i++)
    {
        if(buttons[i] == nullptr)
        {
            buttons[i]=button;
            button->ID=i;
            functions[i]=func;
        }
    }
    buttons.push_back(button);
    button->ID=buttons.size()-1;
    functions.push_back(func);
    return true;
}

bool MWindow::removeButton(Button *button)
{
    for(int i(0) ; i < (int)buttons.size() ; i++)
    {
        if(buttons[i] == button)
        {
            buttons[i]->setParent(nullptr);
            buttons[i] = nullptr;
            return true;
        }
    }
    return false;
}

bool MWindow::removeButton(int index)
{
    try
    {
        buttons.at(index)->setParent(nullptr);
        buttons.at(index) = nullptr;
    }
    catch (std::out_of_range const& exc) // My compiler (GCC 4.7.1) does not want of std::out_of_range or std::logic_error...why ?
    {
        return false;
    }
    return true;
}

void MWindow::update()
{
    window->clear();

    for(int i(0) ; i < (int)buttons.size(); i++)
        if(buttons[i]!=nullptr)
            window->draw(*buttons[i]);

    window->display();
}
 

Button.cpp :
#include "MWindow.h"

Button::Button(std::string const& adress, std::string const& adressO, std::string const& adressL, std::string const& adressD) : \
    parent(nullptr), texture(), textureOver(), textureLeaned(), textureDisabled(), chkClicked(new sf::Thread(&Button::checkClicked, this)), \
    enabled(false), mouseOver(false), leaned(false), hidden(false), ID(-1)
{
    changeTexture(adress);
    changeTextureOver(adressO);
    changeTextureLeaned(adressL);
    changeTextureDisabled(adressD);
}

Button::~Button()
{
    delete chkClicked;
}

bool Button::setParent(MWindow *newParent, void (*newFunc)())
{
    if(!newParent->addButton(this, newFunc))
        return false;

    delete chkClicked;
    parent=newParent;
    if(parent == nullptr || newFunc == nullptr)
    {
        setEnabled(false);
        ID=-1;
        return false;
    }
    else
    {
        setEnabled(true);
        chkClicked=new sf::Thread(newFunc, parent);
    }

    return true;
}

MWindow* Button::getParent()
{
    return parent;
}

void Button::setEnabled(bool yay)
{
    if((enabled && yay) || hidden)
    {
        return;
    }
    else if(yay)
    {
        enabled=true;
        chkClicked->launch();
    }
    else
    {
        enabled=false;
        setTexture(textureDisabled);
    }
}

bool Button::getEnabled()
{
    return enabled;
}

void Button::setHidden(bool hide)
{
    if(hide)
    {
        setEnabled(false);
        setTexture(sf::Texture());
        hidden=true;
    }
    else
    {
        hidden=false;
        setEnabled(true);
    }
}

bool Button::getHidden()
{
    return hidden;
}

void Button::changeTexture(std::string const& adress)
{
    texture.loadFromFile(adress);
}

void Button::changeTextureOver(std::string const& adress)
{
    textureOver.loadFromFile(adress);
}

void Button::changeTextureLeaned(std::string const& adress)
{
    textureLeaned.loadFromFile(adress);
}

void Button::changeTextureDisabled(std::string const& adress)
{
    textureDisabled.loadFromFile(adress);
}

void Button::checkClicked()
{
    while(enabled)
    {
        if(parent->event.type == sf::Event::MouseMoved)
        {
            if(getGlobalBounds().contains(sf::Vector2<float>(parent->event.mouseMove.x, parent->event.mouseMove.y)))
            {//if the mouse is in the button...
                mouseOver=true;
                setTexture(textureOver);
            }
            else
            {
                mouseOver=false;
                setTexture(texture);
            }
        }
        else if(parent->event.type == sf::Event::MouseButtonPressed && parent->event.mouseButton.button == sf::Mouse::Right && mouseOver)
        {
            leaned=true;
            setTexture(textureLeaned);
        }
        else if(parent->event.type == sf::Event::MouseButtonReleased && parent->event.mouseButton.button == sf::Mouse::Right && leaned)
        {
            if(getGlobalBounds().contains(sf::Vector2<float>(parent->event.mouseButton.x, parent->event.mouseButton.y)))
            {
                setTexture(textureOver);
                parent->functions[ID]();
            }
            else
            {
                setTexture(texture);
                mouseOver=false;
            }
            leaned=false;
        }
    }
} // In instantiation of 'void sf::priv::ThreadFunctorWithArg<F, A>::run() [with F = void (*)(); A = MWindow*]': required from here
 

Merci d'avance pour vos éclaircissements.
« Modifié: Septembre 24, 2014, 11:52:13 am par Glân de Brylan »
Vous aussi, ayez chaque jour une pensée pour tous ces gamins qui s'imaginent faire un MMORPG touts seuls, et ce avant même d'avoir appris le C++.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : [Threads] Too many arguments to function
« Réponse #1 le: Septembre 24, 2014, 10:21:14 am »
On peut dire que tu ne lâches pas le morceau toi...

Déjà une chose : utilise code=cpp, pas juste code, pour avoir la coloration syntaxique. Ca ne s'est pas mis magiquement dans tes posts précédents, c'est toujours moi qui passe dérrière toi pour éditer tes posts.

Ensuite concernant l'erreur, tu passes au thread une fonction non-membre ne prenant aucun paramètre, et tu lui files avec ça un paramètre. Ca ne colle pas, le paramètre n'est utilisé nulle part dans la fonction à lancer par le thread, d'où l'erreur.

Et je me répète : tu n'as aucun besoin de threads pour faire ce que tu fais, à part te créer des erreurs de compilation à la pelle, parce que tu ne comprends de toute évidence pas complètement ce que tu fais, ça ne sert strictement à rien.
Laurent Gomila - SFML developer

Glân de Brylan

  • Jr. Member
  • **
  • Messages: 83
  • Je pense ce que je dis et le dis comme je le pense
    • Voir le profil
Re : [Threads] Too many arguments to function
« Réponse #2 le: Septembre 24, 2014, 11:02:13 am »
Mais j'aimerais que cliquer sur le bouton permette d'exécuter une fonction sans bloquer le reste du programme, c'est à ça que servent les threads, non ?
Vous aussi, ayez chaque jour une pensée pour tous ces gamins qui s'imaginent faire un MMORPG touts seuls, et ce avant même d'avoir appris le C++.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : [Threads] Too many arguments to function
« Réponse #3 le: Septembre 24, 2014, 11:24:37 am »
Pourquoi est-ce que la fonction associée au clic devrait être threadée ? Typiquement il va s'agir d'une action très ponctuelle (changement d'état, de propriété d'un objet, etc.) qui ne va pas bloquer le reste du programme.

Et quand bien même tu associerais à ton bouton une fonction ayant besoin de tourner dans un thread, ce n'est pas au bouton de gérer ça, c'est la fonction associée au clic qui devrait gérer le thread.

Tu devrais y aller dans le bon sens : commence par faire un truc simple, et ajoute les fonctionnalités dont tu auras réellement besoin, là où tu en auras besoin. Là tu tu es en train de concevoir un bouton trop compliqué pour rien, et résultat, tu passes ton temps à résoudre des poblèmes que tu ne devrais même pas avoir. Fais un bouton qui peut appeler une fonction en réaction à un clic (hint: std::function). Ensuite si tu as besoin de threads (et je doute que ce soit le cas) alors mets-en dans la ou les fonctions qui en auront besoin. Pas dans le bouton.
Laurent Gomila - SFML developer

Glân de Brylan

  • Jr. Member
  • **
  • Messages: 83
  • Je pense ce que je dis et le dis comme je le pense
    • Voir le profil
Re : [Threads] Too many arguments to function
« Réponse #4 le: Septembre 24, 2014, 11:52:01 am »
D'accord. C'est vrai que j'ai un peu tendance à vouloir utiliser toute nouvelle fonctionnalité (nouvelle pour moi) et du coup je fais n'importe quoi.
Merci pour l'aide.
Vous aussi, ayez chaque jour une pensée pour tous ces gamins qui s'imaginent faire un MMORPG touts seuls, et ce avant même d'avoir appris le C++.