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