void scrollpane::add_widget(widget* w, int x, int y, int z_order)
{
	if (w == NULL)
		return;

	widget_map::iterator itor = std::find_if(content_.begin(), content_.end(), widget_finder(w));
	if (itor != content_.end())
		return;

	scrollpane_widget spw(w, x, y, z_order);

	w->set_clip_rect(client_area());
	content_.insert(std::pair<int, scrollpane_widget>(z_order, spw));

	position_widget(spw);

	// Recalculates the whole content size
	update_content_size();
}
int main()
{

  // Limitation 1: none of the make functions permit the specification of custom deleters.

  auto widgetDeleter = [](Widget* pw) { /* ... */ };
  
  std::unique_ptr<Widget, decltype(widgetDeleter)>
    upw(new Widget(), widgetDeleter);
  
  std::shared_ptr<Widget> spw(new Widget(), widgetDeleter);


  // Limitation 2: within the make function, the perfect forwarding code uses
  // parentheses, not braces.  The bad news of this is that if you want to
  // construct your pointed-to object using a braced initializer, you must use
  // new directly.

  {
    auto upv = std::make_unique<std::vector<int>>(10,20);
    auto spv = std::make_shared<std::vector<int>>(10,20);
  }
  {
    // create std::initializer_list
    auto initList = {10, 20};

    // create std::vector using std::initializer_list ctor
    auto spv = std::make_shared<std::vector<int>>(initList);
  }


  // Limitation 3 (only for make_shared)
  auto pBigObj =                         // create very large
    std::make_shared<ReallyBigType>();   // object via
                                         // std::make_shared
  
               // create std::shared_ptrs and std::weak_ptrs to
               // large object, use them to work with it
  
               // final std::shared_ptr to object destroyed here,
               // but std::weak_ptrs to it remain
  
               // during this period, memory formerly occupied
               // by large object remains allocated
  
               // final std::weak_ptr to object destroyed here;
               // memory for control block and object is released

  std::shared_ptr<ReallyBigType> pBigObj(new ReallyBigType);
                                       // create very large
                                       // object via new

               // as before, create std::shared_ptrs and
               // std::weak_ptrs to object, use them with it

               // final std::shared_ptr to object destroyed here,
               // but std::weak_ptrs to it remain
               // memory for object is deallocated

               // during this period, only memory for
               // the control block remains allocated

               // final std::weak_ptr to object destroyed here;
               // memory for control block and object is released


  // Exception-unsafe call

  processWidget(                                  // as before
    std::shared_ptr<Widget>(new Widget, cusDel),  // potential
    computePriority()                             // resource
  );                                              // leak!


  // Exception-safe calls

  std::shared_ptr<Widget> spw(new Widget, cusDel);

  processWidget(spw, computePriority());      // correct, but not
                                              // optimal; see below

  processWidget(std::move(spw),               // both efficient and
                computePriority());           // exception safe

}
int main()
{

    /* For std::unique_ptr, the type of the deleter is part of the type of the
     * smart pointer.  For std::shared_ptr, it's not.
     */

    std::cout << "Part 1: deleter type being part or not" << std::endl;
    
    std::unique_ptr<                       // deleter type is
      Widget, decltype(loggingDel)         // part of ptr type
      > upw(new Widget, loggingDel);
    
    std::shared_ptr<Widget>                // deleter type is not
      spw(new Widget, loggingDel);         // part of ptr type
    
    
    /* The std::shared_ptr design is more flexible: the type of the custom deleter
     * is not part of the shared_ptr type, so the following things are for example
     * possible:
     * 
     *   -> can be placed in containers of objects of the shared_ptr type
     *   -> they can be assigned to one another
     *   -> they can be passed to a function taking a parameter of
     *      type std::shared_ptr<Widget>.
     *   -> ...
     * 
     * None of these things can be done with std::unique_ptrs that differ in the
     * types of their custom deleters, because the type of the custom deleter would
     * affect the type of the std::unique_ptr.
     */
     
    std::cout << "Part 2: std::shared_ptr design being more flexible" << std::endl;

    auto customDeleter1 = [](Widget *pw) { makeLogentry(pw); delete pw; };  // custom deleters,
    auto customDeleter2 = [](Widget *pw) { makeLogentry(pw); delete pw; };  // each with a
                                                                            // different type
    
    std::shared_ptr<Widget> pw1(new Widget, customDeleter1);
    std::shared_ptr<Widget> pw2(new Widget, customDeleter2);
    
    std::vector<std::shared_ptr<Widget>> vpw { pw1, pw2 };


   /*
    * BAD BAD BAD: constructing more than one std::shared_ptr from a single
    * raw pointer results in undefined behavior.
    */

    std::cout << "Part 3: std::shared_ptr construction error" << std::endl;
   
    //auto pw = new Widget;
    // 
    //std::shared_ptr<Widget> spw1(pw, loggingDel);  // create control
    //                                               // block for *pw
    //
    //std::shared_ptr<Widget> spw2(pw, loggingDel);  // create 2nd
    //                                               // control block
    //                                               // for *pw!
    
    std::shared_ptr<Widget> spw1(new Widget,       // direct use of new
                                 loggingDel);
    
    std::shared_ptr<Widget> spw2(spw1);            // spw2 uses same
                                                   // control block as spw1

    std::cout << "Part 4: right before end of main" << std::endl;
}