text: // Document/View sample for Boost.Signals2.
  // Expands on doc_view_acm.cpp example by using boost::signals2::deconstruct
  // as a post-constructing factory function.
  //
  // Copyright Keith MacDonald 2005.
  // Copyright Frank Mori Hess 2009.
  //
  // Use, modification and
  // distribution is subject to the Boost Software License, Version
  // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  // http://www.boost.org/LICENSE_1_0.txt)
  // For more information, see http://www.boost.org
  
  #include <iostream>
  #include <string>
  #include <boost/bind.hpp>
  #include <boost/ref.hpp>
  #include <boost/signals2/deconstruct.hpp>
  #include <boost/signals2/signal.hpp>
  #include <boost/shared_ptr.hpp>
  
  class Document
  {
  public:
    typedef boost::signals2::signal<void ()>  signal_t;
  
  public:
    Document()
    {}
  
    /* Connect a slot to the signal which will be emitted whenever
      text is appended to the document. */
    boost::signals2::connection connect(const signal_t::slot_type &subscriber)
    {
      return m_sig.connect(subscriber);
    }
  
    void append(const char* s)
    {
      m_text += s;
      m_sig();
    }
  
    const std::string& getText() const
    {
      return m_text;
    }
  
  private:
    signal_t    m_sig;
    std::string m_text;
  };
  
  class TextView
  {
  public:
    /* This adl_postconstruct function will be found
    via argument-dependent lookup when using boost::signals2::deconstruct. */
    template<typename T>
      friend void adl_postconstruct(const boost::shared_ptr<T> &view_sp, TextView *view, Document& doc)
    {
      view->m_document = &doc;
      {
        typedef Document::signal_t::slot_type slot_type;
        slot_type myslot(&TextView::refresh, view);
        doc.connect(myslot.track(view_sp));
      }
    }
  
    void refresh() const
    {
      std::cout << "TextView: " << m_document->getText() << std::endl;
    }
  private:
    // give boost::signals2::deconstruct access to private constructor
    friend class boost::signals2::deconstruct_access;
    // private constructor to force use of deconstruct
    TextView()
    {}
  
    Document*               m_document;
  };
  
  class HexView
  {
  public:
    /* This adl_postconstruct function will be found
    via argument-dependent lookup when using boost::signals2::deconstruct. */
    template<typename T>
      friend void adl_postconstruct(const boost::shared_ptr<T> &view_sp, HexView *view, Document& doc)
    {
      view->m_document = &doc;
      {
        typedef Document::signal_t::slot_type slot_type;
        slot_type myslot(&HexView::refresh, view);
        doc.connect(myslot.track(view_sp));
      }
    }
  
    void refresh() const
    {
      const std::string&  s = m_document->getText();
  
      std::cout << "HexView:";
  
      for (std::string::const_iterator it = s.begin(); it != s.end(); ++it)
        std::cout << ' ' << std::hex << static_cast<int>(*it);
  
      std::cout << std::endl;
    }
  private:
    // give boost::signals2::deconstruct access to private constructor
    friend class boost::signals2::deconstruct_access;
    // private constructor to force use of deconstruct
    HexView()
    {}
  
    Document*               m_document;
  };
  
  namespace bs2 = boost::signals2;
  
  int main(int argc, char* argv[])
  {
    Document    doc;
    boost::shared_ptr<TextView> v1 = bs2::deconstruct<TextView>().postconstruct(boost::ref(doc));
    boost::shared_ptr<HexView> v2 = bs2::deconstruct<HexView>().postconstruct(boost::ref(doc));
  
    doc.append(argc >= 2 ? argv[1] : "Hello world!");
  
    v2.reset(); // destroy the HexView, automatically disconnecting
    doc.append("  HexView should no longer be connected.");
  
    return 0;
  }
  