Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Using a lambda as a slot problem



  • I'm using last version of VS2019 and when I use a lambda as a slot in QTimer::singleShot() compiler give me follow error

    no instance of overloaded function matches the argument list argument types are: (int, SwitchBlock , lambda []void ()->void)

    although I made a similiar connection successfully in another class.

    Here is the class

    #pragma once
    
    #include "Inert.h"
    
    class SwitchBlock : public Inert
    {
    	private:
    
    		static bool pressed;
    		int animation_counter;
    
    		//textures
    		QPixmap texture_spawning[11];
    		QPixmap texture_active[3];
    		QPixmap texture_smashed;
    		
    		bool spawning;
    		bool active;
    
    	public:
    
    		SwitchBlock(QPoint position);
    
    		static bool IsPressed() { return pressed; }
    		virtual std::string name() { return "SwitchBlock"; }
    		virtual void animate();
    		virtual void hit(Object* what, Direction fromDir);
    };
    

    This is the method in which I tried to use the lambda as a slot

    
    void SwitchBlock::hit(Object* what, Direction fromDir)
    {
    	Mario* mario = dynamic_cast<Mario*>(what);
    	if (mario && fromDir == UP)
    	{
    		active = false;
    		collidable = false;
    		Game::instance()->stopMusic();
    		pressed = true;
    		Sounds::instance()->play("switch-hit");
    		QTimer::singleShot(200, this, [this] { pressed = false; });
    
    
    	}
    }
    


  • @Giuseppe97 QTimer::singleShot() needs a QObject instance as receiver to work.
    As far as I can see the is not the case with SwichtBlock?

    But you could use what, but the lambda will be executed in the thread of this instance:

    QTimer::singleShot(200, what, [this]() { pressed = false; });
    

  • Moderators

    @Giuseppe97
    well it's missing some parts, most importantly the parameter list

    QTimer::singleShot(200, this, [this]()->void { pressed = false; });
    


  • @J-Hilk
    Thanks . I suppose I have to study better the syntax of lambdas.



  • @Giuseppe97
    maybe in this way you can avoid to pass this

    QTimer::singleShot(200, this, [&pressed](){ pressed = false; });
    


  • @guerinoni
    I have tried but compiler tells that in capture list SwitchBlock::pressed is not a variable.



  • @Giuseppe97 said in Using a lambda as a slot problem:

    @guerinoni
    I have tried but compiler tells that in capture list SwitchBlock::pressed is not a variable.

    ok then just pass all by reference [&]



  • @guerinoni
    Capturing all by reference cause the initial error QTimer::singleShot': none of the 6 overloads could convert all the argument types


  • Lifetime Qt Champion

    @Giuseppe97 Did you try what @J-Hilk suggested?



  • @jsulm
    Yes but it doesn't compile. I have marked the question as solved because for a moment the compiler didn't reject the lambda but when i rebuild the solution the problem was still there. I am also trying to figure out what's the problem by myself through a deep study of lambda syntax.



  • @Giuseppe97 said in Using a lambda as a slot problem:

    QTimer::singleShot(200, this, [this] { pressed = false; });

    You have to add () to define the lambda function ==> QTimer::singleShot(200, this, [this]() { pressed = false; });

    Take a look at https://blog.feabhas.com/2014/03/demystifying-c-lambdas/ to get more details about Lambdas



  • @KroMignon
    Thanks for the link but it doesn't compile.
    UUUpng.png



  • @Giuseppe97 QTimer::singleShot() needs a QObject instance as receiver to work.
    As far as I can see the is not the case with SwichtBlock?

    But you could use what, but the lambda will be executed in the thread of this instance:

    QTimer::singleShot(200, what, [this]() { pressed = false; });
    


  • @KroMignon
    Thanks now it compile. Yes the problem was that SwitchBlock inherits by Inert which inherits by Object class which is a QGraphicsPixmapItem so the use of what doesn't resolve the problem . I could have used multiple inheritance so that SwitchBlock inherits both from QGraphicsPixmapItem and Qobject but I have choosen to move the call of singleShot static method to Game which inherits by QGraphicsView.



  • @Giuseppe97 Oh sorry, I read you code too fast and I read void SwitchBlock::hit(QObject * what,...) instead of void SwitchBlock::hit(Object * what,...)!

    But I this case, you could also use qApp as receiver, so lambda will run in main thread:

    Timer::singleShot(200, qApp, [this]() { pressed = false; });
    


  • @KroMignon
    Ok thanks I will do this way since for the application (a level of Super Mario Bros 3 (NES)) I didn't use multiple threads . By the way this is my first "serious" project (for a university exam) and I am amazingly surprised of how many things I have learned since I have started.


Log in to reply