summaryrefslogtreecommitdiff
path: root/ace/Value_Ptr.h
blob: 4c05f2884099a28ec335fbdab807ca136449230f (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// -*- C++ -*-

//==========================================================================
/**
 *  @file Value_Ptr.h
 *
 *  $Id$
 *
 *  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 <algorithm>

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 (void) { delete this->p_; }

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

    /// Pointer operator.
    T * operator-> (void) 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;
    }

#ifndef ACE_LACKS_MEMBER_TEMPLATES

    // Compiler can't handle member templates so we lose converting
    // copy operations.

    /// 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;
    }

#endif  /* !ACE_LACKS_MEMBER_TEMPLATES */

  private:

#ifndef ACE_LACKS_MEMBER_TEMPLATES

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

#else

    // Compiler can't handle member templates so we lose converting
    // copy operations.

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

#endif  /* !ACE_LACKS_MEMBER_TEMPLATES */

  private:

#ifndef ACE_LACKS_MEMBER_TEMPLATES
    template <typename U> friend class Value_Ptr;
#endif  /* !ACE_LACKS_MEMBER_TEMPLATES */

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

  };

}

#endif  /* ACE_VALUE_PTR_H */