]> git.tdb.fi Git - ext/sigc++-2.0.git/blob - tests/test_bind.cc
Import libsigc++ 2.10.8 sources
[ext/sigc++-2.0.git] / tests / test_bind.cc
1 // -*- c++ -*-
2 /* Copyright 2002, The libsigc++ Development Team
3  *  Assigned to public domain.  Use as you wish without restriction.
4  */
5
6 #include "testutilities.h"
7 #include <sigc++/adaptors/bind.h>
8 #include <sigc++/functors/slot.h>
9 #include <sstream>
10 #include <string>
11 #include <cstdlib>
12
13 namespace
14 {
15 std::ostringstream result_stream;
16
17 struct foo : public sigc::functor_base
18 {
19   // choose a type that can hold all return values
20   typedef int result_type;
21
22   int operator()(int i)
23   {
24     result_stream << "foo(int " << i << ") ";
25     return i > 0;
26   }
27
28   int operator()(int i, int j)
29   {
30     result_stream << "foo(int " << i << ", int "<< j << ") ";
31     return i + j;
32   }
33
34   int operator()(int i, int j, int k)
35   {
36     result_stream << "foo(int " << i << ", int " << j << ", int " << k << ") ";
37     return 0;
38   }
39 };
40
41 struct foo_void : public sigc::functor_base
42 {
43   typedef void result_type;
44
45   void operator()(int i)
46   {
47     result_stream << "foo_void(int " << i << ")";
48   }
49 };
50
51 int bar(int i, int j)
52 {
53   result_stream << "bar(int " << i << ", int " << j << ") ";
54   return i + j;
55 }
56
57 bool simple(bool test)
58 {
59   result_stream << "simple(bool " << test << ") ";
60   return test;
61 }
62
63 void egon(std::string& str)
64 {
65   result_stream << "egon(string '" << str << "')";
66   str = "egon was here";
67 }
68
69
70 struct book : public sigc::trackable
71 {
72   book(const std::string& name) : name_(name) {}
73
74   //non-copyable:
75   book(const book&) = delete;
76   book& operator=(const book&) = delete;
77   
78   //non movable:
79   book(book&&) = delete;
80   book& operator=(book&&) = delete;
81
82   std::string& get_name()  { return name_; }
83   operator std::string& () { return get_name(); }
84
85 private:
86   std::string name_;
87 };
88
89 } // end anonymous namespace
90
91 int main(int argc, char* argv[])
92 {
93   auto util = TestUtilities::get_instance();
94
95   if (!util->check_command_args(argc, argv))
96     return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE;
97
98   // replacing bind1st, bind2nd
99   result_stream << sigc::bind<0>(foo(), -12345)(5);
100   util->check_result(result_stream, "foo(int -12345, int 5) -12340");
101
102   result_stream << sigc::bind<1>(foo(), -12345)(5);
103   util->check_result(result_stream, "foo(int 5, int -12345) -12340");
104
105   // multiple
106   sigc::bind(foo(), 1, 2)();
107   util->check_result(result_stream, "foo(int 1, int 2) ");
108
109   // bind from end
110   sigc::bind<-1>(foo(), 4)(3);
111   util->check_result(result_stream, "foo(int 3, int 4) ");
112
113   sigc::bind(foo(), 4)(3);
114   util->check_result(result_stream, "foo(int 3, int 4) ");
115
116   // used together
117   sigc::bind<0>(sigc::bind<0>(foo(), 7), 8)();
118   util->check_result(result_stream, "foo(int 7, int 8) ");
119
120   // void return
121   sigc::bind(foo(), 9, 10)(11); // (only returned void if typeof() would be supported)
122   util->check_result(result_stream, "foo(int 11, int 9, int 10) ");
123
124   sigc::bind(foo_void(), 12)();
125   util->check_result(result_stream, "foo_void(int 12)");
126
127   // function pointer instead of functor
128   sigc::bind(&bar, 13, 14)();
129   util->check_result(result_stream, "bar(int 13, int 14) ");
130
131   // method pointer instead of functor
132   book test_book("otto");
133   result_stream << sigc::bind<0>(&book::get_name, std::ref(test_book))();
134   util->check_result(result_stream, "otto");
135
136   // test return type of bind_functor::operator() overload with no arguments
137   result_stream << sigc::bind(foo(), 15)();
138   util->check_result(result_stream, "foo(int 15) 1");
139
140   result_stream << sigc::bind(&simple, true)();
141   util->check_result(result_stream, "simple(bool 1) 1");
142
143   // test references
144   std::string str("guest book");
145   sigc::bind(&egon, std::ref(str))(); // Tell bind that it shall store a reference.
146   result_stream << " " << str; // (This cannot be the default behaviour: just think about what happens if str dies!)
147   util->check_result(result_stream, "egon(string 'guest book') egon was here");
148
149   sigc::slot<void> sl;
150   {
151     book guest_book("karl");
152     sl = sigc::bind(&egon, std::ref(guest_book));
153     sl();
154     result_stream << " " << static_cast<std::string&>(guest_book);
155     util->check_result(result_stream, "egon(string 'karl') egon was here");
156   } // auto-disconnect
157
158   sl();
159   util->check_result(result_stream, "");
160   // This causes a crash when using g++ 3.3.4 or 3.3.5 (but not 3.4.x) when not specifying
161   // the exact template specialization in visit_each_type() - see the comments there.
162   // It looks like the auto-disconnect does not work, so the last sl() call tries
163   // to access the guest_book data again.
164
165   return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE;
166 }