29
29
application using that toolkit should handle the user clicking on it.</para >
30
30
31
31
<para >In C the callbacks are generally handled by the application calling a
32
- 'register' function and passing a pointer to a function and a <literal remap =" tt" >void *</literal >
32
+ 'register' function and passing a pointer to a function and a <literal remap =" tt" >void*</literal >
33
33
argument, eg.</para >
34
34
35
35
<programlisting >
36
- void clicked(void * data);
36
+ void clicked(void* data);
37
37
38
- button * okbutton = create_button("ok");
38
+ button* okbutton = create_button("ok");
39
39
static char somedata[] = "This is some data I want the clicked() function to have";
40
40
41
41
register_click_handler(okbutton, clicked, somedata);
42
42
</programlisting >
43
43
44
44
<para >When clicked, the toolkit will call <literal remap =" tt" >clicked()</literal > with the data pointer passed
45
- to the <literal remap =" tt" >register_click_handler</literal > function.</para >
45
+ to the <literal remap =" tt" >register_click_handler() </literal > function.</para >
46
46
47
47
<para >This works in C, but is not typesafe. There is no compile-time way of
48
48
ensuring that <literal remap =" tt" >clicked()</literal > isn't expecting a struct of some sort instead of a
49
- <literal remap =" tt" >char *</literal >.</para >
49
+ <literal remap =" tt" >char*</literal >.</para >
50
50
51
51
<para >As C++ programmers, we want type safety. We also want to be able to use
52
52
things other than free-standing functions as callbacks.</para >
@@ -55,7 +55,8 @@ register_click_handler(okbutton, clicked, somedata);
55
55
the things that can be used as a callback:
56
56
<itemizedlist >
57
57
<listitem ><para >A free-standing function as in the example</para ></listitem >
58
- <listitem ><para >A functor objects that defines operator()</para ></listitem >
58
+ <listitem ><para >A functor object that defines operator() (a lambda expression
59
+ is such an object)</para ></listitem >
59
60
<listitem ><para >A pointer-to-a-member-function and an instance of an object on which to invoke it (the
60
61
object should inherit from <literal remap =" tt" >sigc::trackable</literal >)</para ></listitem >
61
62
</itemizedlist ></para >
@@ -96,7 +97,7 @@ public:
96
97
97
98
void run();
98
99
99
- sigc::signal< void> signal_detected;
100
+ sigc::signal< void() > signal_detected;
100
101
};
101
102
</programlisting >
102
103
@@ -107,7 +108,7 @@ public:
107
108
<programlisting >
108
109
void warn_people()
109
110
{
110
- cout << "There are aliens in the carpark!" << endl;
111
+ std:: cout << "There are aliens in the carpark!" << std:: endl;
111
112
}
112
113
113
114
int main()
@@ -121,6 +122,11 @@ int main()
121
122
}
122
123
</programlisting >
123
124
125
+ <para >You can use a lambda expression instead of sigc::ptr_fun().</para >
126
+ <programlisting >
127
+ mydetector.signal_detected.connect( [](){ warn_people(); } );
128
+ </programlisting >
129
+
124
130
<para >Pretty simple really - you call the <literal remap =" tt" >connect()</literal > method on the signal to
125
131
connect your function. <literal remap =" tt" >connect()</literal > takes a <literal remap =" tt" >slot</literal > parameter (remember slots
126
132
are capable of holding any type of callback), so you convert your
@@ -175,6 +181,12 @@ int main()
175
181
176
182
<para >This code is in example2.cc, which can be compiled in the same way as
177
183
example1.cc</para >
184
+
185
+ <para >It's possible to use a lambda expression instead of sigc::mem_fun(),
186
+ but it's not recommended, if the class derives from <literal remap =" tt" >sigc::trackable</literal >.
187
+ With a lambda expression you would lose the automatic disconnection that the
188
+ combination of <literal remap =" tt" >sigc::trackable</literal > and sigc::mem_fun()
189
+ offers.</para >
178
190
</sect1 >
179
191
180
192
<sect1 >
@@ -198,22 +210,25 @@ public:
198
210
199
211
void run();
200
212
201
- sigc::signal< void, std::string> signal_detected; // changed
213
+ sigc::signal< void( std::string) > signal_detected; // changed
202
214
};
203
215
</programlisting >
204
216
205
217
<para >The only line I had to change was the signal line (in <literal remap =" tt" >run()</literal > I need to change
206
218
my code to supply the argument when I emit the signal too, but that's not shown
207
219
here).</para >
208
220
209
- <para >The name of the type is '<literal remap =" tt" >sigc::signal</literal >'. The template parameters are the return type, then the argument types.</para >
221
+ <para >The name of the type is '<literal remap =" tt" >sigc::signal</literal >'.
222
+ The template parameters are the return type, then the argument types in parentheses.
223
+ (libsigc++2 also accepts a different syntax, with a comma between the return type
224
+ and the parameter types. That syntax is deprecated, though.)</para >
210
225
211
226
<para >The types in the function signature are in the same order as the template
212
227
parameters, eg:</para >
213
228
214
229
<programlisting >
215
- sigc::signal< void, std::string>
216
- void function(std::string foo);
230
+ sigc::signal< void( std::string) >
231
+ void function(std::string foo);
217
232
</programlisting >
218
233
219
234
<para >So now you can update your alerter (for simplicity, lets go back to the
@@ -222,7 +237,7 @@ sigc::signal<void, std::string>
222
237
<programlisting >
223
238
void warn_people(std::string where)
224
239
{
225
- cout << "There are aliens in " << where << "!" << endl;
240
+ std:: cout << "There are aliens in " << where << "!" << std:: endl;
226
241
}
227
242
228
243
int main()
@@ -269,7 +284,7 @@ int main()
269
284
<para >A signal is an instance of a template, named <literal remap =" tt" >sigc::signal</literal >.
270
285
The template arguments are the types,
271
286
in the order they appear in the function signature that can be connected to that
272
- signal; that is the return type, then the argument types.</para >
287
+ signal; that is the return type, then the argument types in parentheses .</para >
273
288
274
289
<para >To provide a signal for people to connect to, you must make available an
275
290
instance of that <literal remap =" tt" >sigc::signal</literal >. In <literal remap =" tt" >AlienDetector</literal > this was done
@@ -297,7 +312,7 @@ void AlienDetector::run()
297
312
{
298
313
sleep(3); // wait for aliens
299
314
signal_detected("the carpark"); // this is the std::string version, looks like
300
- // they landed in the carpark afterall .
315
+ // they landed in the carpark after all .
301
316
}
302
317
</programlisting >
303
318
</sect1 >
@@ -308,7 +323,7 @@ void AlienDetector::run()
308
323
about the return value of the last registered one, it's quite straightforward:</para >
309
324
310
325
<programlisting >
311
- sigc::signal< int> somesignal;
326
+ sigc::signal< int() > somesignal;
312
327
int a_return_value;
313
328
314
329
a_return_value = somesignal.emit();
@@ -390,23 +405,21 @@ myaliendetector.signal_detected.connect( sigc::hide<std::string>( sigc::pt
390
405
<para >A similar topic is retyping. Perhaps you have a signal that takes an <literal remap =" tt" >int</literal >, but
391
406
you want to connect a function that takes a <literal remap =" tt" >double</literal >.</para >
392
407
393
- <para >This can be achieved with the <literal remap =" tt" >sigc::retype</literal > template. <literal remap =" tt" >retype</literal > has template arguments
394
- just like <literal remap =" tt" >sigc::signal</literal > - return value, signal types.</para >
395
-
396
- <para >It's a function template that takes a <literal remap =" tt" >sigc::slot</literal >, and returns a <literal remap =" tt" >sigc::slot</literal >. eg.</para >
408
+ <para >This can be achieved with the <literal remap =" tt" >sigc::retype()</literal > template.
409
+ It takes a <literal remap =" tt" >sigc::slot</literal >, and returns a <literal remap =" tt" >sigc::slot</literal >. eg.</para >
397
410
398
411
<programlisting >
399
412
void dostuff(double foo)
400
413
{
401
414
}
402
415
403
- sigc::signal< void, int> asignal;
416
+ sigc::signal< void( int) > asignal;
404
417
405
- asignal.connect( sigc::retype< void, int > ( slot (& dostuff) ) );
418
+ asignal.connect( sigc::retype( sigc::ptr_fun (& dostuff) ) );
406
419
</programlisting >
407
420
408
- <para >If you only want to change the return type, you can use <literal remap =" tt" >sigc::retype_return</literal >.
409
- <literal remap =" tt" >retype_return</literal > needs only one template argument.</para >
421
+ <para >If you only want to change the return type, you can use <literal remap =" tt" >sigc::retype_return() </literal >.
422
+ <literal remap =" tt" >retype_return() </literal > needs one template argument, the new return type .</para >
410
423
</sect1 >
411
424
</chapter >
412
425
0 commit comments