8

I want to use lambda expressions in connection with goocanvas in gtk++. For my understanding this means that I must be able to put my lambda in a sigc++ functor.

I tried something like that:

sigc::slot<bool,  const Glib::RefPtr<Goocanvas::Item>& , GdkEventMotion* > slot2=
    [](  const Glib::RefPtr<Goocanvas::Item>& item, GdkEventMotion* ev)->bool
    {
        cout << "Lambda " << endl; return false;
    };

((Glib::RefPtr<Goocanvas::Item>&)item1)->signal_motion_notify_event().connect( slot2);

But this will not compile.

Is there a chance to get sigc working with lambdas or better gtkmm directly without the sigc++ intermediate :-)

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
Klaus
  • 24,205
  • 7
  • 58
  • 113

3 Answers3

7

For void returning functions/methods with no arguments, it's pretty simple, e.g. (gcc 4.6, 4.7):

 fileButton.signal_pressed().connect([this]{on_file_button_clicked();});

Unfortunately I've not been able to get value returning or argument taking methods to compile, and have to resort to sigc::mem_fun() for those. There seems to be some recent activity to fix this, for example, this commit. If you have sigc++ version 2.2.11 or greater, you can try defining SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE, but I have no idea how well this works.

Also related is this bug report.

ergosys
  • 47,835
  • 5
  • 49
  • 70
  • The SIGC_FUNCTORS macro certainly resolved the compilation error for me when connecting a signal to a non-void-returning, argument-taking, and value-capturing lambda. Whether my project does anything useful right now is a very diffferent question, but the macro definitely seems good! – underscore_d Dec 06 '15 at 01:01
  • As of now on my Debian testing system, it seems this macro is no longer required. Even better! And the aforementioned project has suddenly started going very well indeed :-) – underscore_d Feb 15 '16 at 21:28
4

I found the following code snipped which do the job. I have no idea how this interacts with the sigc++ lib, but I can use it for simple cases. Maybe someone else can take a look on it.

            #include <type_traits>
            #include <sigc++/sigc++.h>
            namespace sigc
            {   
                template <typename Functor>
                    struct functor_trait<Functor, false>
                    {   
                        typedef decltype (::sigc::mem_fun (std::declval<Functor&> (), 
                                    &Functor::operator())) _intermediate;

                        typedef typename _intermediate::result_type result_type;
                        typedef Functor functor_type;
                    };  
            }   

UPDATE: Libsigc is now able to handle lambas without any additional user code. The above code must be removed if any current versions is used.

Klaus
  • 24,205
  • 7
  • 58
  • 113
  • Where did you find this? Somebody else posted it on SO with a link showing the original source, but I can't find my way back to that. Always try to include sources! If it's on a mailing list, for instance, the surrounding discussion might be highly relevant. – underscore_d Dec 06 '15 at 01:02
  • 1
    @underscore_d I can't remember after years where I find a code snipped. But using a search engine results in: https://mail.gnome.org/archives/libsigc-list/2012-January/msg00000.html. – Klaus Dec 07 '15 at 08:56
1

A demo using the gtkmm helloworld example:

#include "helloworld.h"
#include <iostream>

HelloWorld::HelloWorld()
    : m_button("Hello World")  // creates a new button with label "Hello World".
{
    // Sets the border width of the window.
    set_border_width(10);

    // When the button receives the "clicked" signal, it will call the
    // on_button_clicked() method defined below.
    m_button.signal_clicked().connect(
        sigc::mem_fun(*this, &HelloWorld::on_button_clicked));

    m_button.signal_clicked().connect([=]() { std::cout << "hello lambda\n"; });

    // This packs the button into the Window (a container).
    add(m_button);

    // The final step is to display this newly created widget...
    m_button.show();
}

HelloWorld::~HelloWorld() {}

void HelloWorld::on_button_clicked() {
    std::cout << "hello method" << std::endl;
}

Lambda works.

qed
  • 22,298
  • 21
  • 125
  • 196
  • Yes, 6 years after the question was asked, the question is not longer valid ;) You are right, after some weeks of asking my question here, libsigc++ was updated. – Klaus Nov 29 '18 at 12:39
  • Lambdas not returning a value worked even in 2012, so this example is totally irrelevant. – facetus Apr 29 '21 at 09:52