blob: f7e4be43d986f178967acf738b66466b33237af4 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef CSV_DYN_HXX
#define CSV_DYN_HXX
namespace csv
{
/** Dyn owns an object on the heap, which will be automatically
deleted in its D'tor.
Dyn's main purpose is for class members on the heap:
You can't forget to delete them in the D'tor. Constness will be transfered
to the hold object.
Dyn forbids the CopyC'tor and operator=(). So you can't incidentally
run into problems with compiler defined CopyC'tor or operator=() of the
owning class. If you need those, you have to define them explicitely - as
you should do anyway with all classes, that own members on the heap.
Dyn also works with incomplete types.
You only need to write
class DX;
but needn't include #include <DX>.hxx.
This is a difference to std::auto_ptr, where it is not absolutely clear
if it is allowed to use it with incomplete types.
You can also use Dyn within function bodies, to make them exception safe.
@attention
If you use Dyn with an incomplete type, the owning class needs to
define a non-inline D'tor. Else the compiler will complain.
*/
template <class DX>
class Dyn
{
public:
// LIFECYCLE
/// From now on, let_dpObject is owned by this Dyn-object.
explicit Dyn(
DX * let_dpObject = 0);
~Dyn();
// OPERATORS
/** This deletes a prevoiusly existing dpObject!
From now on, let_dpObject is owned by this Dyn-object.
*/
Dyn<DX> & operator=(
DX * let_dpObject);
/// @return true, if any valid object is hold, false else.
operator bool() const;
const DX * operator->() const;
DX * operator->();
const DX & operator*() const;
DX & operator*();
// OPERATIONS
/** @return The hold object on the heap.
@ATTENTION
The caller of the function is responsible to delete
the returned object
@postcond
this->dpObject == 0.
*/
DX * Release();
// INQUIRY
/// Shorthand for operator->(), if implicit overloading of -> can not be used.
const DX * Ptr() const;
// ACCESS
/// Shorthand for operator->(), if implicit overloading of -> can not be used.
DX * Ptr();
/// So const objects can return mutable pointers to the owned object.
DX * MutablePtr() const;
private:
/* Does NOT set dpObject to zero! Because it is only used
internally in situations where dpObject is set immediately
after.
*/
void Delete();
/** Forbidden function!
-------------------
Help ensure, that classes with
dynamic pointers use a selfdefined copy constructor
and operator=(). If the default versions of these
functions are used, the compiler will throw an error.
**/
Dyn( const Dyn<DX> & );
/** Forbidden function!
-------------------
Help ensure, that classes with
dynamic pointers use a selfdefined copy constructor
and operator=(). If the default versions of these
functions are used, the compiler will throw an error.
**/
Dyn<DX> & operator=( const Dyn<DX> & );
// DATA
/// An owned heap object. Needs to be deleted by this class.
DX * dpObject;
};
// IMPLEMENTATION
template <class DX>
void
Dyn<DX>::Delete()
{
if (dpObject != 0)
delete dpObject;
}
template <class DX>
inline
Dyn<DX>::Dyn( DX * let_dpObject )
: dpObject(let_dpObject) {}
template <class DX>
inline
Dyn<DX>::~Dyn()
{ Delete(); }
template <class DX>
inline Dyn<DX> &
Dyn<DX>::operator=( DX * let_dpObject )
{
if ( dpObject == let_dpObject )
return *this;
Delete();
dpObject = let_dpObject;
return *this;
}
template <class DX>
inline
Dyn<DX>::operator bool() const
{ return dpObject != 0; }
template <class DX>
inline
const DX *
Dyn<DX>::operator->() const
{ return dpObject; }
template <class DX>
inline DX *
Dyn<DX>::operator->()
{ return dpObject; }
template <class DX>
inline const DX &
Dyn<DX>::operator*() const
{ csv_assert(dpObject != 0);
return *dpObject;
}
template <class DX>
inline DX &
Dyn<DX>::operator*()
{ csv_assert(dpObject != 0);
return *dpObject;
}
template <class DX>
inline DX *
Dyn<DX>::Release()
{ DX * ret = dpObject;
dpObject = 0;
return ret;
}
template <class DX>
inline const DX *
Dyn<DX>::Ptr() const
{ return dpObject; }
template <class DX>
inline DX *
Dyn<DX>::Ptr()
{ return dpObject; }
template <class DX>
inline DX *
Dyn<DX>::MutablePtr() const
{ return dpObject; }
} // namespace csv
#ifndef CSV_HIDE_DYN
#define Dyn ::csv::Dyn
#endif
#endif