Boost Learning Series 4-event processing (II)

Source: Internet
Author: User
A synthesizer is a class that overload the operator () operator. This operator is automatically called, and two iterators are passed in to point to all the returned values of a specific signal. The above example uses the Standard C ++ algorithm STD: min_element () to determine and return the smallest value.

Unfortunately, we cannot pass an algorithm like STD: min_element () directly to boost: signal as a template parameter. Boost: signal requires this synthesizer to define a type named result_type to describe the type returned by the operator () operator. This type is missing in the Standard C ++ algorithm, so a corresponding error occurs during compilation.

In addition to analyzing the returned values, the synthesizer can also save them.

#include <boost/signal.hpp> #include <iostream> #include <vector> #include <algorithm> int func1() {   return 1; } int func2() {   return 2; } template <typename T> struct min_element {   typedef T result_type;   template <typename InputIterator>   T operator()(InputIterator first, InputIterator last) const   {     return T(first, last);   } }; int main() {   boost::signal<int (), min_element<std::vector<int> > > s;   s.connect(func1);   s.connect(func2);   std::vector<int> v = s();   std::cout << *std::min_element(v.begin(), v.end()) << std::endl; } 

In this example, all return values are saved in a vector and then returned by S.

3. Connect to connections

Functions can be managed through the help of the Connect () and disconnect () methods provided by boost: signal. Because connect () returns a value of the boost: Signals: Connection type, which can be managed by other methods.

#include <boost/signal.hpp> #include <iostream> void func() {   std::cout << "Hello, world!" << std::endl; } int main() {   boost::signal<void ()> s;   boost::signals::connection c = s.connect(func);   s();   c.disconnect(); } 

The boost: Signal disconnect () method needs to pass in a function pointer, while the disconnect () method on the connection object that calls boost: Signals: connection directly skips this parameter.

In addition to the disconnect () method, boost: Signals: connection also provides other methods, such as block () and unblock ().

#include <boost/signal.hpp> #include <iostream> void func() {   std::cout << "Hello, world!" << std::endl; } int main() {   boost::signal<void ()> s;   boost::signals::connection c = s.connect(func);   c.block();   s();   c.unblock();   s(); } 

The above program will only execute func () once (). Although the signalSIt is triggered twice, but func () is not called when triggered for the first time because of the ConnectionCIt is actually blocked by block () calls. Since unblock () is called before the second trigger, func () is correctly executed afterwards.

In addition to boost: Signals: connection, there is also a class named boost: Signals: scoped_connection, which will automatically release the connection during the analysis.

#include <boost/signal.hpp> #include <iostream> void func() {   std::cout << "Hello, world!" << std::endl; } int main() {   boost::signal<void ()> s;   {     boost::signals::scoped_connection c = s.connect(func);   }   s(); } 

Because the connection objectCThe function is destroyed before the signal is triggered, so func () is not called.

Boost: Signals: scoped_connection is actually derived from boost: Signals: connection, so it provides the same method. The difference between them is that the connection is automatically released when the boost: Signals: scoped_connection is parsed.

Although boost: Signals: scoped_connection does make it easier to automatically release connections, this type of object still needs to be managed. In other cases, connections can also be automatically released without the need to manage these objects.

#include <boost/signal.hpp> #include <boost/bind.hpp> #include <iostream> #include <memory> class world {   public:     void hello() const     {       std::cout << "Hello, world!" << std::endl;     } }; int main() {   boost::signal<void ()> s;   {     std::auto_ptr<world> w(new world());     s.connect(boost::bind(&world::hello, w.get()));   }   std::cout << s.num_slots() << std::endl;   s(); } 

The above program uses boost. bind to associate an object method with a signal. This object is destroyed before the signal is triggered, which may cause problems. We do not pass actual objectsWAnd pass only one pointer to boost: BIND (). When S () is actually called, the object directed by this pointer no longer exists.

You can modify this program as follows so that once the objectWThe connection is automatically released after it is destroyed.

#include <boost/signal.hpp> #include <boost/bind.hpp> #include <iostream> #include <memory> class world :   public boost::signals::trackable {   public:     void hello() const     {       std::cout << "Hello, world!" << std::endl;     } }; int main() {   boost::signal<void ()> s;   {     std::auto_ptr<world> w(new world());     s.connect(boost::bind(&world::hello, w.get()));   }   std::cout << s.num_slots() << std::endl;   s(); } 

If you execute it now, num_slots () returns 0 to ensure that the method on the destroyed object is not called. The only modification is to let the world class inherit from boost: Signals: trackable. When you use object pointers instead of object copies to associate functions with signals, boost: Signals: trackable can significantly simplify connection management.

Iv. Exercises

Compile a program and define a class named button, which indicates a clickable button in the GUI. Add two methods add_handler () and remove_handler () to the class. They both require a function name as a parameter. If the click () method is called, the registered function is executed in order.

Test your code as follows, create a button class instance, and write a message from the event processor to the standard output stream. Call the click () function to simulate clicking this button with the mouse.

5. Answers

I really don't understand this boost library. I tried versions 33, 42, and 47, prompting three strange header file errors. At first I suspected it was my old compiler vc6.0 problem, later, when I switched to open-source eclipse in Linux, the same error was reported. I was speechless and continued to look for problems. The following code was written by myself for verification, after the problem is resolved, I will verify and modify the error.

# Include <boost/bind. HPP> # include <boost/signal. HPP> # include <memory> # include <iostream>/* you can use this method to automatically release the connection and destroy the object after it ends. The most concise method is */class button: Public boost :: signals: trackable {public: button () {} void add_handler () {STD: cout <"handle is added !! "<STD: Endl;} void remove_handler () {STD: cout <" handle is removed !! "<STD: Endl ;}; int main (INT argc, char * argv []) {boost: Signal <void ()> click; STD :: auto_ptr <button> but (New button (); click. connect (boost: BIND (& button: add_handler,. get (); click. connect (boost: BIND (& button: remove_handler,. get (); click (); Return 0 ;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.