Я хочу использовать лямбда-выражения в связи с goocanvas в gtk ++. Для моего понимания это означает, что я должен быть в состоянии поместить свою лямбду в функтор sigc ++.
Я попробовал что-то подобное:
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);
Но это не скомпилируется.
Есть ли шанс заставить sigc работать с лямбдами или лучше с gtkmm напрямую без промежуточного соединения sigc ++ 🙂
Для void, возвращающих функции / методы без аргументов, это довольно просто, например (gcc 4.6, 4.7):
fileButton.signal_pressed().connect([this]{on_file_button_clicked();});
К сожалению, я не смог получить методы, возвращающие значения или принимающие аргументы для компиляции, и мне пришлось прибегнуть к sigc::mem_fun()
для тех. Кажется, есть некоторые недавние действия, чтобы исправить это, например, этот коммит. Если у вас sigc ++ версии 2.2.11 или выше, вы можете попробовать определить SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
, но я понятия не имею, насколько хорошо это работает.
Также связано это этот отчет об ошибке.
Я нашел следующий код, который выполняет работу. Я понятия не имею, как это взаимодействует с библиотекой sigc ++, но я могу использовать ее для простых случаев. Может быть, кто-то еще может взглянуть на это.
#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;
};
}
ОБНОВИТЬ:
Libsigc теперь может обрабатывать lambas без какого-либо дополнительного пользовательского кода. Приведенный выше код должен быть удален, если используются текущие версии.
Демо с использованием Пример gtkmm helloworld:
#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;
}
Лямбда работает.