Skip to content

Commit 720bfb6

Browse files
committed
signal: Add connect_first()
Add connect_first(const slot_base&) and connect_first(slot_base&&) in internal::signal_impl, signal_base, signal_with_accumulator and trackable_signal_with_accumulator. Replace some calls to connect() by connect_first() in test_signal and test_scoped_connection. Fixes #81
1 parent 793d066 commit 720bfb6

File tree

12 files changed

+193
-46
lines changed

12 files changed

+193
-46
lines changed

sigc++/adaptors/bind.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ namespace sigc
5353
* sigc::bind(&foo,1,2,3)(); //fixes all three arguments and calls foo(1,2,3)
5454
* @endcode
5555
*
56-
* The functor sigc::bind() returns can be passed into
57-
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" directly.
56+
* The functor that sigc::bind() returns can be passed directly into
57+
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" or
58+
* @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()".
5859
*
5960
* @par Example:
6061
* @code

sigc++/adaptors/compose.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ namespace sigc
3838
* square_root(9))
3939
* @endcode
4040
*
41-
* The functor sigc::compose() returns can be passed directly into
42-
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()".
41+
* The functor that sigc::compose() returns can be passed directly into
42+
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" or
43+
* @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()".
4344
*
4445
* @par Example:
4546
* @code

sigc++/adaptors/exception_catch.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ namespace sigc
6161
* sigc::exception_catch(&foo, my_catch())();
6262
* @endcode
6363
*
64-
* The functor sigc::exception_catch() returns can be directly passed into
65-
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()".
64+
* The functor that sigc::exception_catch() returns can be passed directly into
65+
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" or
66+
* @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()".
6667
*
6768
* @par Example:
6869
* @code

sigc++/adaptors/hide.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ namespace sigc
5050
* sigc::hide<2>(&foo)(1,2,3); // adds a dummy parameter at the back and calls foo(1,2)
5151
* @endcode
5252
*
53-
* The functor sigc::hide() returns can be directly passed into
54-
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()".
53+
* The functor that sigc::hide() returns can be passed directly into
54+
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" or
55+
* @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()".
5556
*
5657
* @par Example:
5758
* @code

sigc++/adaptors/retype.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ namespace sigc
4141
* @endcode
4242
*
4343
* The functor that sigc::retype() returns can be passed directly into
44-
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()".
44+
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" or
45+
* @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()".
4546
*
4647
* @par Example:
4748
* @code

sigc++/connection.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ namespace sigc
3030
/** Convenience class for safe disconnection.
3131
*
3232
* This may be used to disconnect the referred slot at any time (disconnect()).
33-
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()"
34-
* returns a %sigc::connection.
33+
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" and
34+
* @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()"
35+
* return a %sigc::connection.
3536
*
3637
* @code
3738
* sigc::connection conn = sig.connect(sigc::mem_fun(a, &A::foo));

sigc++/scoped_connection.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ namespace sigc
3434
*
3535
* You will use sigc::scoped_connection by constructing it from a ‘normal’,
3636
* unscoped @ref sigc::connection, such as those returned by
37-
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()", thus
38-
* ‘wrapping’ the connection in a scoped_connection, adding auto-disconnection.
37+
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" and
38+
* @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()",
39+
* thus ‘wrapping’ the connection in a scoped_connection, adding auto-disconnection.
3940
* It can also be assigned from an unscoped connection, in which case, if there
4041
* was a previous slot referred to by the scoped connection, it is disconnected.
4142
*

sigc++/signal.h

Lines changed: 97 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -374,14 +374,14 @@ struct signal_emit<void, void, T_arg...>
374374
/** Signal declaration.
375375
* %signal_with_accumulator can be used to connect() slots that are invoked
376376
* during subsequent calls to emit(). Any functor or slot
377-
* can be passed into connect(). It is converted into a slot
377+
* can be passed into connect() or connect_first(). It is converted into a slot
378378
* implicitly.
379379
*
380380
* If you want to connect one signal to another, use make_slot()
381381
* to retrieve a functor that emits the signal when invoked.
382382
*
383-
* Be careful if you directly pass one signal into the connect()
384-
* method of another: a shallow copy of the signal is made and
383+
* Be careful if you directly pass one signal into the connect() or
384+
* connect_first() method of another: a shallow copy of the signal is made and
385385
* the signal's slots are not disconnected until both the signal
386386
* and its clone are destroyed, which is probably not what you want!
387387
*
@@ -401,8 +401,8 @@ class signal_with_accumulator : public signal_base
401401
public:
402402
using slot_type = slot<T_return(T_arg...)>;
403403

404-
/** Add a slot to the list of slots.
405-
* Any functor or slot may be passed into connect().
404+
/** Add a slot at the end of the list of slots.
405+
* Any functor or slot may be passed into %connect().
406406
* It will be converted into a slot implicitly.
407407
* The returned connection may be stored for disconnection
408408
* of the slot at some later point. It stays valid until
@@ -426,7 +426,7 @@ class signal_with_accumulator : public signal_base
426426
return connection(slot_base);
427427
}
428428

429-
/** Add a slot to the list of slots.
429+
/** Add a slot at the end of the list of slots.
430430
* @see connect(const slot_type& slot_).
431431
*
432432
* @newin{2,8}
@@ -438,6 +438,45 @@ class signal_with_accumulator : public signal_base
438438
return connection(slot_base);
439439
}
440440

441+
/** Add a slot at the beginning of the list of slots.
442+
* Any functor or slot may be passed into %connect_first().
443+
* It will be converted into a slot implicitly.
444+
* The returned connection may be stored for disconnection
445+
* of the slot at some later point. It stays valid until
446+
* the slot is disconnected from the signal.
447+
* std::function<> and C++11 lambda expressions are functors.
448+
* These are examples of functors that can be connected to a signal.
449+
*
450+
* %std::bind() creates a functor, but this functor typically has an
451+
* %operator()() which is a variadic template.
452+
* Our functor_trait can't deduce the result type
453+
* of such a functor. If you first assign the return value of %std::bind()
454+
* to a std::function, you can connect the std::function to a signal.
455+
*
456+
* @param slot_ The slot to add to the list of slots.
457+
* @return A connection.
458+
*
459+
* @newin{3,6}
460+
*/
461+
connection connect_first(const slot_type& slot_)
462+
{
463+
auto iter = signal_base::connect_first(slot_);
464+
auto& slot_base = *iter;
465+
return connection(slot_base);
466+
}
467+
468+
/** Add a slot at the beginning of the list of slots.
469+
* @see connect_first(const slot_type& slot_).
470+
*
471+
* @newin{3,6}
472+
*/
473+
connection connect_first(slot_type&& slot_)
474+
{
475+
auto iter = signal_base::connect_first(std::move(slot_));
476+
auto& slot_base = *iter;
477+
return connection(slot_base);
478+
}
479+
441480
/** Triggers the emission of the signal.
442481
* During signal emission all slots that have been connected
443482
* to the signal are invoked unless they are manually set into
@@ -505,14 +544,14 @@ class signal_with_accumulator : public signal_base
505544

506545
/** signal can be used to connect() slots that are invoked
507546
* during subsequent calls to emit(). Any functor or slot
508-
* can be passed into connect(). It is converted into a slot
547+
* can be passed into connect() or connect_first(). It is converted into a slot
509548
* implicitly.
510549
*
511550
* If you want to connect one signal to another, use make_slot()
512551
* to retrieve a functor that emits the signal when invoked.
513552
*
514-
* Be careful if you directly pass one signal into the connect()
515-
* method of another: a shallow copy of the signal is made and
553+
* Be careful if you directly pass one signal into the connect() or
554+
* connect_first() method of another: a shallow copy of the signal is made and
516555
* the signal's slots are not disconnected until both the signal
517556
* and its clone are destroyed, which is probably not what you want!
518557
*
@@ -634,13 +673,14 @@ class signal<T_return(T_arg...)> : public signal_with_accumulator<T_return, void
634673
/** Signal declaration.
635674
* %trackable_signal_with_accumulator can be used to connect() slots that are invoked
636675
* during subsequent calls to emit(). Any functor or slot
637-
* can be passed into connect(). It is converted into a slot implicitly.
676+
* can be passed into connect() or connect_first(). It is converted into a slot
677+
* implicitly.
638678
*
639679
* If you want to connect one signal to another, use make_slot()
640680
* to retrieve a functor that emits the signal when invoked.
641681
*
642-
* Be careful if you directly pass one signal into the connect()
643-
* method of another: a shallow copy of the signal is made and
682+
* Be careful if you directly pass one signal into the connect() or
683+
* connect_first() method of another: a shallow copy of the signal is made and
644684
* the signal's slots are not disconnected until both the signal
645685
* and its clone are destroyed, which is probably not what you want!
646686
*
@@ -664,8 +704,8 @@ class trackable_signal_with_accumulator
664704
public:
665705
using slot_type = slot<T_return(T_arg...)>;
666706

667-
/** Add a slot to the list of slots.
668-
* Any functor or slot may be passed into connect().
707+
/** Add a slot at the end of the list of slots.
708+
* Any functor or slot may be passed into %connect().
669709
* It will be converted into a slot implicitly.
670710
* The returned connection may be stored for disconnection
671711
* of the slot at some later point. It stays valid until
@@ -689,7 +729,7 @@ class trackable_signal_with_accumulator
689729
return connection(slot_base);
690730
}
691731

692-
/** Add a slot to the list of slots.
732+
/** Add a slot at the end of the list of slots.
693733
* @see connect(const slot_type& slot_).
694734
*/
695735
connection connect(slot_type&& slot_)
@@ -699,6 +739,45 @@ class trackable_signal_with_accumulator
699739
return connection(slot_base);
700740
}
701741

742+
/** Add a slot at the beginning of the list of slots.
743+
* Any functor or slot may be passed into %connect_first().
744+
* It will be converted into a slot implicitly.
745+
* The returned connection may be stored for disconnection
746+
* of the slot at some later point. It stays valid until
747+
* the slot is disconnected from the signal.
748+
* std::function<> and C++11 lambda expressions are functors.
749+
* These are examples of functors that can be connected to a signal.
750+
*
751+
* %std::bind() creates a functor, but this functor typically has an
752+
* %operator()() which is a variadic template.
753+
* Our functor_trait can't deduce the result type
754+
* of such a functor. If you first assign the return value of %std::bind()
755+
* to a std::function, you can connect the std::function to a signal.
756+
*
757+
* @param slot_ The slot to add to the list of slots.
758+
* @return A connection.
759+
*
760+
* @newin{3,6}
761+
*/
762+
connection connect_first(const slot_type& slot_)
763+
{
764+
auto iter = signal_base::connect_first(slot_);
765+
auto& slot_base = *iter;
766+
return connection(slot_base);
767+
}
768+
769+
/** Add a slot at the beginning of the list of slots.
770+
* @see connect_first(const slot_type& slot_).
771+
*
772+
* @newin{3,6}
773+
*/
774+
connection connect_first(slot_type&& slot_)
775+
{
776+
auto iter = signal_base::connect_first(std::move(slot_));
777+
auto& slot_base = *iter;
778+
return connection(slot_base);
779+
}
780+
702781
/** Triggers the emission of the signal.
703782
* During signal emission all slots that have been connected
704783
* to the signal are invoked unless they are manually set into
@@ -772,14 +851,14 @@ class trackable_signal_with_accumulator
772851

773852
/** %trackable_signal can be used to connect() slots that are invoked
774853
* during subsequent calls to emit(). Any functor or slot
775-
* can be passed into connect(). It is converted into a slot
854+
* can be passed into connect() or connect_first(). It is converted into a slot
776855
* implicitly.
777856
*
778857
* If you want to connect one signal to another, use make_slot()
779858
* to retrieve a functor that emits the signal when invoked.
780859
*
781-
* Be careful if you directly pass one signal into the connect()
782-
* method of another: a shallow copy of the signal is made and
860+
* Be careful if you directly pass one signal into the connect() or
861+
* connect_first() method of another: a shallow copy of the signal is made and
783862
* the signal's slots are not disconnected until both the signal
784863
* and its clone are destroyed, which is probably not what you want!
785864
*

sigc++/signal_base.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ signal_impl::connect(slot_base&& slot_)
128128
return insert(slots_.end(), std::move(slot_));
129129
}
130130

131+
signal_impl::iterator_type
132+
signal_impl::connect_first(const slot_base& slot_)
133+
{
134+
return insert(slots_.begin(), slot_);
135+
}
136+
137+
signal_impl::iterator_type
138+
signal_impl::connect_first(slot_base&& slot_)
139+
{
140+
return insert(slots_.begin(), std::move(slot_));
141+
}
142+
131143
void
132144
signal_impl::add_notification_to_iter(const signal_impl::iterator_type& iter)
133145
{
@@ -260,6 +272,18 @@ signal_base::connect(slot_base&& slot_)
260272
return impl()->connect(std::move(slot_));
261273
}
262274

275+
signal_base::iterator_type
276+
signal_base::connect_first(const slot_base& slot_)
277+
{
278+
return impl()->connect_first(slot_);
279+
}
280+
281+
signal_base::iterator_type
282+
signal_base::connect_first(slot_base&& slot_)
283+
{
284+
return impl()->connect_first(std::move(slot_));
285+
}
286+
263287
signal_base::iterator_type
264288
signal_base::insert(iterator_type i, const slot_base& slot_)
265289
{

0 commit comments

Comments
 (0)