summaryrefslogtreecommitdiff
path: root/ACE/ace/Value_Ptr.h
blob: 2f558b98c159a0bfc86f16d291ce7833e3670105 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// -*- C++ -*-

//==========================================================================
/**
 *  @file Value_Ptr.h
 *
 *  Value_Ptr implementation based on code in Herb Sutter's book "More
 *  Exceptional C++".
 *
 *  @author Ossama Othman <ossama@dre.vanderbilt.edu>
 */
//==========================================================================

#ifndef ACE_VALUE_PTR_H
#define ACE_VALUE_PTR_H

#include /**/ "ace/config-lite.h"

#include <algorithm>

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

namespace ACE
{
  /**
   * @struct VP_traits
   *
   * @brief @c Value_Ptr traits template structure.
   *
   * The @c Value_Ptr template class delegates some operations to this
   * template traits structure.
   *
   * Specialize this trait template if cloning through copy
   * construction is not sufficient.  For example, to avoid slicing
   * when copying an object through a base class pointer, one can
   * implement a virtual "clone" method that can be used to
   * polymorphically invoke the appropriate cloning operation(s).
   * That virtual method would then be invoked by the @c VP_traits\<\>
   * specialization.
   */
  template <typename T>
  struct VP_traits
  {
    /// Copy the given object.
    static T * clone (T const * p) { return new T (*p); }
  };

  /**
   * @class Value_Ptr
   *
   * @brief Smart pointer implementation designed for use as a class
   *        member.
   *
   * Using a @c std::auto_ptr\<\> as a class member is sometimes
   * problematic since ownership of memory is transferred when copying
   * such members.  This @c Value_Ptr class is explicitly designed to
   * avoid such problems by performing copies of the underlying object
   * rather than transfer ownership.  This, for example, allows it to
   * be readily used as a member in classes placed inside STL
   * containers.
   *
   * @see Item 31 in "More Exceptional C++" by Herb Sutter.
   */
  template <typename T>
  class Value_Ptr
  {
  public:
    /// Constructor.
    explicit Value_Ptr (T * p = 0) : p_ (p) {}

    /// Destructor.
    ~Value_Ptr () { delete this->p_; }

    /// Deference operator.
    T & operator* () const { return *this->p_; }

    /// Pointer operator.
    T * operator-> () const { return this->p_; }

    /// Non-throwing swap operation used to make assignment strongly
    /// exception-safe.
    /**
     * @note As implemented, the swap operation may not work correctly
     *       for @c auto_ptr\<\>s, but why would one use an @c
     *       auto_ptr\<\> as the template argument for this particular
     *       template class!?
     */
    void swap (Value_Ptr & other) { std::swap (this->p_, other.p_); }

    /// Copy constructor.
    Value_Ptr (Value_Ptr const & other)
      : p_ (create_from (other.p_)) { }

    /// Assignment operator.
    Value_Ptr & operator= (Value_Ptr const & other)
    {
      // Strongly exception-safe.
      Value_Ptr temp (other);
      this->swap (temp);
      return *this;
    }

    /// Converting copy constructor.
    template <typename U>
    Value_Ptr (Value_Ptr<U> const & other)
      : p_ (create_from (other.p_)) { }

    /// Converting assignment operator.
    template <typename U>
    Value_Ptr & operator= (Value_Ptr<U> const & other)
    {
      // Strongly exception-safe.
      Value_Ptr temp (other);
      this->swap (temp);
      return *this;
    }

  private:
    /// Copying method invoked when copy constructing.
    template <typename U>
    T * create_from (U const * p) const
    {
      return p ? VP_traits<U>::clone (p) : 0;
    }

  private:
    template <typename U> friend class Value_Ptr;

    /// Object owned by this @c Value_Ptr.
    T * p_;
  };

}

ACE_END_VERSIONED_NAMESPACE_DECL

#endif  /* ACE_VALUE_PTR_H */