00001 // more/utility.h -- various utilities
00002 // Copyright (C) 1998--2002 Petter Urkedal
00003
00004 // This file is free software; you can redistribute it and/or modify
00005 // it under the terms of the GNU General Public License as published by
00006 // the Free Software Foundation; either version 2 of the License, or
00007 // (at your option) any later version.
00008
00009 // This file is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00012 // GNU General Public License for more details.
00013
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00017
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction. Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License. This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027
00028 // $Id: utility.h,v 1.4 2002/08/24 13:59:27 petter_urkedal Exp $
00029
00030
00031 #ifndef MORE_GEN_UTILITY_H
00032 #define MORE_GEN_UTILITY_H
00033
00034 #include <utility>
00035 #include <functional>
00036 #include <string>
00037 #include <typeinfo>
00038 #include <stdexcept>
00039 #include <cassert>
00040 #include <more/bits/config.h>
00041
00042
00043 namespace more {
00044 namespace gen {
00045
00046 struct instance_counter
00047 {
00048 instance_counter()
00049 : ic(new int)
00050 {
00051 *ic = 0;
00052 }
00053
00054 instance_counter(const instance_counter& x)
00055 : ic(x.ic)
00056 {
00057 ++*ic;
00058 }
00059
00060 ~instance_counter()
00061 {
00062 if (!*ic)
00063 delete ic;
00064 else
00065 --*ic;
00066 }
00067
00068 instance_counter& operator=(const instance_counter& x)
00069 {
00070 if (!*ic)
00071 delete ic;
00072 ic = x.ic;
00073 ++*ic;
00074 return *this;
00075 }
00076
00077 bool is_unique() const { return !*ic; }
00078
00079 private:
00080 mutable int* ic;
00081 };
00082
00083 // --- handle ---
00084 //
00085
00086 template<typename T> class handle;
00087
00088 /** \class handle_base utility.h more/gen/utility.h
00089 ** Base class for the template argument of a \c handle. */
00090 struct handle_data
00091 {
00092 handle_data() : m_refcnt(1) {}
00093 void ref() const { ++m_refcnt; }
00094 unsigned int unref() const { return --m_refcnt; }
00095
00096 private:
00097 template<typename T> friend class handle;
00098 mutable int m_refcnt;
00099 };
00100
00101 /** \class handle utility.h more/gen/utility.h
00102 ** Utility class to deal with reference counting. This class can
00103 ** be used as a base class for the user-visible class, whereas the
00104 ** data members are placed in a separate type, given as the
00105 ** template argument \a T. The handle can also be a data-member.
00106 ** In any case, the copy constructor, the assigment operator and
00107 ** the destructor shall be invoked when the superclass or containing
00108 ** class is copied, assigned to ar destructed, respectively.
00109 **
00110 ** A const handle is treated as a constant object referring to
00111 ** <i>mutable</i> data, since constness of the data is anyway violated
00112 ** when a non-constant handle to the same data also exists. But
00113 ** the member functions of the object derived from the handle
00114 ** should nevertheless reflect the constness of the data. The
00115 ** important consequence of this semanic, is that the
00116 ** copy-constructor can be declared `const&', and thus the classes
00117 ** will interact more normally with STL headers, and in particular
00118 ** the extensions in `more/lambda.h'. */
00119 template<typename T>
00120 struct handle
00121 {
00122 handle() : m_ptr(0) {}
00123
00124 explicit handle(T* p) : m_ptr(p) {}
00125
00126 handle(handle const& x)
00127 : m_ptr(x.m_ptr)
00128 {
00129 if (m_ptr)
00130 ++m_ptr->m_refcnt;
00131 }
00132
00133 handle& operator=(handle const& x)
00134 {
00135 if (m_ptr && !--m_ptr->m_refcnt)
00136 delete m_ptr;
00137 m_ptr = x.m_ptr;
00138 if (m_ptr)
00139 ++m_ptr->m_refcnt;
00140 return *this;
00141 }
00142
00143 ~handle()
00144 {
00145 if (m_ptr && !--m_ptr->m_refcnt)
00146 delete m_ptr;
00147 }
00148
00149 operator bool() const { return m_ptr; }
00150
00151 bool is_owner() const { return m_ptr->m_refcnt == 1; }
00152
00153 void check_data() const
00154 {
00155 #ifndef MORE_DEBUG
00156 if (!m_ptr)
00157 throw std::logic_error(
00158 std::string("more::gen::handle: "
00159 "Accessing invalid object, typeid = ")
00160 + typeid(*this).name());
00161 #endif
00162 }
00163
00164 T* datachk() const
00165 {
00166 check_data();
00167 return m_ptr;
00168 }
00169
00170 T* data() const { return m_ptr; }
00171
00172 T* data_ref() const { m_ptr->ref(); return m_ptr; }
00173
00174 // T* operator()() const { return m_ptr; }
00175
00176 /** Set the handle to point to \a ptr. The caller looses
00177 ** ownership of \a ptr. */
00178 void set_data(T* ptr)
00179 {
00180 if (m_ptr && !--m_ptr->m_refcnt)
00181 delete m_ptr;
00182 m_ptr = ptr;
00183 }
00184
00185 private:
00186 mutable T *m_ptr;
00187 };
00188
00189 /** \class noncopyable utility.h more/utility.h
00190 **
00191 ** Classes derived from this can not be copied or assigned. Since
00192 ** C++ provies a default copy constructor and copy assignment
00193 ** operator for classes which does not define them, it is necessary
00194 ** to explicitely state that copying is not allow; which is done
00195 ** with this common ideom. */
00196 struct noncopyable
00197 {
00198 noncopyable() {}
00199 private:
00200 noncopyable(noncopyable const&) {}
00201 noncopyable const& operator=(noncopyable const&) { return *this; }
00202 };
00203
00204 /** \class refpair utility.h more/gen/utility.h
00205 **
00206 ** Like a pair, but contains references which can be assigned to. */
00207 template<typename T, typename U>
00208 struct refpair
00209 {
00210 /** The type of the first component. */
00211 typedef T first_type;
00212 /** The type of the second component. */
00213 typedef U second_type;
00214 /** Construct a pair of references to \c x and \c y. */
00215 refpair(T& x, U& y) : first(x), second(y) {}
00216 /** Construct a copy. */
00217 refpair(refpair const& rp) : first(rp.first), second(rp.second) {}
00218 /** Assign the values of \c p to the references in this pair. */
00219 refpair& operator=(std::pair<T, U> const& p)
00220 {
00221 first = p.first;
00222 second = p.second;
00223 return *this;
00224 }
00225 /** The first member of the pair. */
00226 T& first;
00227 /** The second member of the pair. */
00228 U& second;
00229 };
00230
00231 /** Creates a refpair. */
00232 template<typename T, typename U>
00233 inline refpair<T, U> tie(T& x, U& y) { return refpair<T, U>(x, y); }
00234
00235
00236 /** \class select1st utility.h more/gen/utility.h
00237 **
00238 ** A functional which returns a reference to the first component of
00239 ** a pair-like type. */
00240 template<typename Pair>
00241 struct select1st : std::unary_function<Pair, typename Pair::first_type>
00242 {
00243 typename Pair::first_type&
00244 operator()(Pair& x) const
00245 {
00246 return x.first;
00247 }
00248 };
00249
00250 /** \class select2nd utility.h more/gen/utility.h
00251 **
00252 ** A functional which returns a reference to the second component
00253 ** of a pair-like type. */
00254 template<typename Pair>
00255 struct select2nd : std::unary_function<Pair, typename Pair::second_type>
00256 {
00257 typename Pair::second_type&
00258 operator()(Pair& x) const
00259 {
00260 return x.second;
00261 }
00262 };
00263
00264 }} // more::gen
00265
00266 #endif