Skip to content

Commit b154e84

Browse files
rherilierkjellahl
authored andcommitted
signal_connect: Add helper functions to ease connecting functions or methods to signals
Those helper functions have 2 main usages: * avoid writing template parameters in case of method or function overloading; * wrap use of sigc::mem_fun or sigc::ptr_fun when possible. unsupported cases: * lambda functions; * std::function (or alike); * volatile functions; * const? volatile methods; * binding with sigc::bind.
1 parent 8181576 commit b154e84

File tree

9 files changed

+258
-0
lines changed

9 files changed

+258
-0
lines changed

sigc++/filelist.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ sigc_public_h = \
2727
scoped_connection.h \
2828
signal.h \
2929
signal_base.h \
30+
signal_connect.h \
3031
slot.h \
3132
trackable.h \
3233
tuple-utils/tuple_cdr.h \

sigc++/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ sigc_h_files = [
2525
'scoped_connection.h',
2626
'signal.h',
2727
'signal_base.h',
28+
'signal_connect.h',
2829
'slot.h',
2930
'trackable.h',
3031
'type_traits.h',

sigc++/sigc++.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
#include <sigc++/connection.h>
120120
#include <sigc++/scoped_connection.h>
121121
#include <sigc++/trackable.h>
122+
#include <sigc++/signal_connect.h>
122123
#include <sigc++/adaptors/adaptors.h>
123124
#include <sigc++/functors/functors.h>
124125

sigc++/signal_base.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,22 @@ struct SIGC_API signal_impl_holder
281281
* a @ref sigc::slot<T_return(T_arg...)> "sigc::slot"
282282
* and connected to a signal. See @ref slot "Slots" and
283283
* @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()".
284+
*
285+
* Use @ref sigc::signal_connect() to connect a method or function to a signal
286+
* without having to explicitly write the required template parameters in case
287+
* of method or function overloading.
288+
*
289+
* @code
290+
* sigc::signal<void(int)> sig;
291+
* void fun(int);
292+
* void fun(double);
293+
* sig.connect(sigc::ptr_fun<void, int>(fun));
294+
* // or more simply:
295+
* sigc::signal_connect(sig, fun);
296+
* @endcode
297+
*
298+
* It can also be used as a replacement for calling signal::connect() with a
299+
* sigc::mem_fun() or a sigc::ptr_fun().
284300
*/
285301

286302
// TODO: When we can break ABI, let signal_base derive from trackable again,

sigc++/signal_connect.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright 2024, The libsigc++ Development Team
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2.1 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, write to the Free Software
16+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+
*
18+
*/
19+
20+
#ifndef SIGC_SIGNAL_CONNECT_H
21+
#define SIGC_SIGNAL_CONNECT_H
22+
23+
#include <sigc++/signal.h>
24+
#include <sigc++/functors/ptr_fun.h>
25+
#include <sigc++/functors/mem_fun.h>
26+
27+
namespace sigc
28+
{
29+
30+
/** Connect a function to a signal
31+
* @param signal The signal to connect to.
32+
* @param fun The function that should be wrapped.
33+
* @return A connection.
34+
*
35+
* @ingroup signal
36+
*/
37+
template<typename T_return, typename... T_arg>
38+
inline connection
39+
signal_connect(signal<T_return(T_arg...)>& signal, T_return (*fun)(T_arg...))
40+
{
41+
return signal.connect(ptr_fun<T_return, T_arg...>(fun));
42+
}
43+
44+
/** Connect a non-const method to a signal
45+
* @param signal The signal to connect to.
46+
* @param obj Reference to object instance the functor should operate on.
47+
* @param fun Pointer to method that should be wrapped.
48+
* @return A connection.
49+
*
50+
* @ingroup signal
51+
*/
52+
template<typename T_return, typename T_obj, typename... T_arg>
53+
inline connection
54+
signal_connect(signal<T_return(T_arg...)>& signal, /**/ T_obj& obj, T_return (T_obj::*fun)(T_arg...))
55+
{
56+
return signal.connect(mem_fun<T_return, T_obj, T_obj, T_arg...>(obj, fun));
57+
}
58+
59+
/** Connect a const method to a signal
60+
* @param signal The signal to connect to.
61+
* @param obj Reference to object instance the functor should operate on.
62+
* @param fun Pointer to method that should be wrapped.
63+
* @return A connection.
64+
*
65+
* @ingroup signal
66+
*/
67+
#if SIGC_MSC
68+
/* MSVC needs to distinguish object's class and method's class (using the
69+
* template parameter T_obj2) to avoid raising error C2672 (no matching
70+
* overloaded function found) when signal_connect(...) is called with a
71+
* const object.
72+
*/
73+
template<typename T_return, typename T_obj, typename T_obj2, typename... T_arg>
74+
inline connection
75+
signal_connect(signal<T_return(T_arg...)>& signal, /*const*/ T_obj& obj, T_return (T_obj2::*fun)(T_arg...) const)
76+
{
77+
return signal.connect(mem_fun<T_return, T_obj, T_obj, T_arg...>(obj, fun));
78+
}
79+
#else
80+
template<typename T_return, typename T_obj, typename... T_arg>
81+
inline connection
82+
signal_connect(signal<T_return(T_arg...)>& signal, /*const*/ T_obj& obj, T_return (T_obj::*fun)(T_arg...) const)
83+
{
84+
return signal.connect(mem_fun<T_return, T_obj, T_obj, T_arg...>(obj, fun));
85+
}
86+
#endif
87+
88+
} /* namespace sigc */
89+
90+
#endif /* SIGC_SIGNAL_CONNECT_H */
91+

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ set (TEST_SOURCE_FILES
4242
test_rvalue_ref.cc
4343
test_scoped_connection.cc
4444
test_signal.cc
45+
test_signal_connect.cc
4546
test_signal_move.cc
4647
test_size.cc
4748
test_slot.cc

tests/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ check_PROGRAMS = \
4949
test_rvalue_ref \
5050
test_scoped_connection \
5151
test_signal \
52+
test_signal_connect \
5253
test_signal_move \
5354
test_size \
5455
test_slot \
@@ -95,6 +96,7 @@ test_retype_return_SOURCES = test_retype_return.cc $(sigc_test_util)
9596
test_rvalue_ref_SOURCES = test_rvalue_ref.cc $(sigc_test_util)
9697
test_scoped_connection_SOURCES = test_scoped_connection.cc $(sigc_test_util)
9798
test_signal_SOURCES = test_signal.cc $(sigc_test_util)
99+
test_signal_connect_SOURCES = test_signal_connect.cc $(sigc_test_util)
98100
test_signal_move_SOURCES = test_signal_move.cc $(sigc_test_util)
99101
test_size_SOURCES = test_size.cc $(sigc_test_util)
100102
test_slot_SOURCES = test_slot.cc $(sigc_test_util)

tests/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ test_programs = [
3131
[[], 'test_rvalue_ref', ['test_rvalue_ref.cc', 'testutilities.cc']],
3232
[[], 'test_scoped_connection', ['test_scoped_connection.cc', 'testutilities.cc']],
3333
[[], 'test_signal', ['test_signal.cc', 'testutilities.cc']],
34+
[[], 'test_signal_connect', ['test_signal_connect.cc', 'testutilities.cc']],
3435
[[], 'test_signal_move', ['test_signal_move.cc', 'testutilities.cc']],
3536
[[], 'test_size', ['test_size.cc', 'testutilities.cc']],
3637
[[], 'test_slot', ['test_slot.cc', 'testutilities.cc']],

tests/test_signal_connect.cc

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/* Copyright 2024, The libsigc++ Development Team
2+
* Assigned to public domain. Use as you wish without restriction.
3+
*/
4+
5+
#include "testutilities.h"
6+
#include <sigc++/trackable.h>
7+
#include <sigc++/signal_connect.h>
8+
9+
namespace
10+
{
11+
12+
TestUtilities* util = nullptr;
13+
std::ostringstream result_stream;
14+
15+
void
16+
fun(int i)
17+
{
18+
result_stream << "fun(int " << i << ")";
19+
}
20+
21+
[[maybe_unused]]
22+
void
23+
fun(double d)
24+
{
25+
result_stream << "fun(double " << d << ")";
26+
}
27+
28+
struct foo : public sigc::trackable
29+
{
30+
void fun_nonconst(int i)
31+
{
32+
result_stream << "foo::fun_nonconst(int " << i << ")";
33+
}
34+
35+
void fun_nonconst(double d)
36+
{
37+
result_stream << "foo::fun_nonconst(double " << d << ")";
38+
}
39+
40+
void fun_const(int i) const
41+
{
42+
result_stream << "foo::fun_const(int " << i << ")";
43+
}
44+
45+
void fun_const(double d) const
46+
{
47+
result_stream << "foo::fun_const(double " << d << ")";
48+
}
49+
};
50+
51+
struct bar : public sigc::trackable
52+
{
53+
void fun_nonconst(int i, int j)
54+
{
55+
result_stream << "bar::fun_nonconst(int " << i << ", int " << j << ")";
56+
}
57+
58+
void fun_nonconst(int i, double j)
59+
{
60+
result_stream << "bar::fun_nonconst(int " << i << ", double " << j << ")";
61+
}
62+
63+
void fun_const(int i, int j) const
64+
{
65+
result_stream << "bar::fun_const(int " << i << ", int " << j << ")";
66+
}
67+
68+
void fun_const(int i, double j) const
69+
{
70+
result_stream << "bar::fun_const(int " << i << ", double " << j << ")";
71+
}
72+
};
73+
74+
void
75+
test_signal_connect_fun()
76+
{
77+
sigc::signal<void(int)> signal;
78+
79+
sigc::signal_connect(signal, &fun);
80+
81+
signal.emit(42);
82+
util->check_result(result_stream, "fun(int 42)");
83+
}
84+
85+
void
86+
test_signal_connect_method_nonconst()
87+
{
88+
sigc::signal<void(int)> signal;
89+
foo f;
90+
91+
sigc::signal_connect(signal, f, &foo::fun_nonconst);
92+
93+
signal.emit(42);
94+
util->check_result(result_stream, "foo::fun_nonconst(int 42)");
95+
}
96+
97+
void
98+
test_signal_connect_method_const()
99+
{
100+
sigc::signal<void(int)> signal;
101+
foo f;
102+
103+
sigc::signal_connect(signal, f, &foo::fun_const);
104+
105+
signal.emit(42);
106+
util->check_result(result_stream, "foo::fun_const(int 42)");
107+
}
108+
109+
void
110+
test_signal_connect_method_const_with_const_object()
111+
{
112+
sigc::signal<void(int)> signal;
113+
const foo f;
114+
115+
sigc::signal_connect(signal, f, &foo::fun_const);
116+
117+
signal.emit(42);
118+
util->check_result(result_stream, "foo::fun_const(int 42)");
119+
}
120+
121+
void
122+
test_signal_connect_method()
123+
{
124+
test_signal_connect_method_nonconst();
125+
test_signal_connect_method_const();
126+
test_signal_connect_method_const_with_const_object();
127+
}
128+
129+
} // end anonymous namespace
130+
131+
int
132+
main(int argc, char* argv[])
133+
{
134+
util = TestUtilities::get_instance();
135+
136+
if (!util->check_command_args(argc, argv))
137+
return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE;
138+
139+
test_signal_connect_fun();
140+
141+
test_signal_connect_method();
142+
143+
return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE;
144+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy