Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement UniquePtr #1

Open
wants to merge 83 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
d32b8e0
Add UniquePtr_UnitTest into the unit tests harness
certik Apr 10, 2015
7f56db9
Add initial implementation of UniquePtr
certik Apr 11, 2015
5d8b307
Make it compile
certik Apr 11, 2015
cacd48f
Add nonnull
certik Apr 11, 2015
7405d58
Use proper var names
certik Apr 11, 2015
d153fc6
Use Ptr as internal pointer
certik Apr 11, 2015
d105a1b
Use two spaces indentation
certik Apr 11, 2015
9c33c3a
Add destructor under the class
certik Apr 11, 2015
fe1eabd
Comment out untested parts
certik Apr 11, 2015
06a5d72
Implement + test getRawPtr
certik Apr 11, 2015
d32a855
Implement getConst
certik Apr 11, 2015
af4c937
Port a test
certik Apr 11, 2015
0160148
Implement uniqueptr, ptr and test dangling
certik Apr 11, 2015
41c93c8
Add dangling2
certik Apr 11, 2015
8b3b854
Add dangling3
certik Apr 11, 2015
b9c91ed
Add dangling4
certik Apr 11, 2015
5cf73ce
Implement reset()
certik Apr 15, 2015
7e61608
Fix reset() in Release mode
certik Apr 15, 2015
b9663f7
Test dereferencing
certik Apr 15, 2015
0f61336
Add another test for deleting
certik Apr 15, 2015
ed14c5a
Test assignments
certik Apr 15, 2015
1ba0502
Add comments
certik Apr 15, 2015
dca4e40
Test dereferencing
certik Apr 15, 2015
5e1d69d
Fix a bug
certik Apr 15, 2015
d112956
More tests
certik Apr 15, 2015
537d2f9
Add another test
certik Apr 15, 2015
e0d9e88
Remove old assert
certik Apr 15, 2015
1b6eab5
Use TEST_EQUALITY and TEST_INEQUALITY
certik Apr 15, 2015
59af22f
Initial implementation of std_unique_ptr_interface
certik Apr 18, 2015
a70c783
Add a deleter
certik Apr 18, 2015
b302f21
Fix it up to compile
certik Apr 18, 2015
57f5c52
Test UniquePtr
certik Apr 18, 2015
aebc374
Test Deleter size
certik Apr 18, 2015
ed478b6
custom deleter
certik Apr 19, 2015
8c14bd5
Test bool from test_unique_ptr_interface
certik May 12, 2015
2d89684
Use and test custom deleter
certik May 12, 2015
9c93135
Test that the object gets deleted
certik May 12, 2015
5d075df
Add more custom object and deleter tests
certik May 12, 2015
30105b4
Make the move constructor work
certik May 12, 2015
6751975
Implement and test release()
certik May 12, 2015
3f725e9
Git rid of temporary methods
certik May 12, 2015
928b2cb
Use release()
certik May 12, 2015
52210c9
Test proper constructor calls
certik May 28, 2015
52c8409
Delete copy constructors/assignments
certik May 28, 2015
7cc6d75
Add move constructor for Deleter and test it
certik May 28, 2015
202346d
Add more tests, fix a bug
certik May 28, 2015
acdc978
Copy the deleter in move constructor and test it
certik May 28, 2015
44d7d46
Fix operator =
certik May 29, 2015
46089aa
Fix and test move assignment
certik May 29, 2015
f122b63
Add and test move assignment from U, E
certik May 29, 2015
8cbc874
Use TEST_ASSERT2() macro
certik May 29, 2015
1d52682
Add another test
certik May 29, 2015
61cd05f
Use it more
certik May 29, 2015
0cc5322
Add TEST_EQUALITY2
certik May 29, 2015
4ec052c
Implement TEST_INEQUALITY2
certik May 29, 2015
bdfa020
Use it
certik May 29, 2015
87af9ed
Add more tests
certik May 29, 2015
28bdf94
More tests
certik May 29, 2015
7538412
Test destructor
certik May 29, 2015
c972fa6
Fix a bug
certik May 29, 2015
e791138
Add a comment
certik May 29, 2015
4f40ec1
Simplify a test
certik May 29, 2015
2f76f10
Implement swap()
certik May 29, 2015
b32a596
Rearrange
certik May 29, 2015
cbfb03e
Refactor
certik May 29, 2015
858fdc9
Implement operator bool
certik May 29, 2015
09c2588
Add a test for swap with deleter
certik May 29, 2015
63efd0e
Override << for nullptr
certik May 29, 2015
8d58166
Use the usual testing macros
certik May 29, 2015
3edc58b
Add a test for =
certik May 31, 2015
b6f7e52
Separate implementation bodies
certik May 31, 2015
2b0bc8f
Add temporary tests
certik May 31, 2015
8ec4933
Use std::tuple
certik May 31, 2015
c9be24c
Add tests for sizeof()
certik May 31, 2015
e25d9a2
Remove obsolete lines
certik May 31, 2015
b0eaf29
Get rid of a warning
certik May 31, 2015
a5f2147
Simplify swap()
certik May 31, 2015
be529c5
Add C++11 ifdef
certik May 31, 2015
5dee9b4
Implement the rest of RCP methods with tests
certik May 31, 2015
4c38d34
Use the operator bool
certik May 31, 2015
5d2f0d7
Move functions around
certik May 31, 2015
1cbbd14
Enable the test in Release mode only
certik Jun 1, 2015
bca9855
Fix UniquePtr ifdef
certik Jun 4, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
378 changes: 378 additions & 0 deletions packages/teuchos/core/src/Teuchos_UniquePtr.hpp
@@ -0,0 +1,378 @@
// @HEADER
// ***********************************************************************
//
// Teuchos: Common Tools Package
// Copyright (2004) Sandia Corporation
//
// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
// license for use of this work by or on behalf of the U.S. Government.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
//
// ***********************************************************************
// @HEADER


#ifndef TEUCHOS_UNIQUEPTR_HPP
#define TEUCHOS_UNIQUEPTR_HPP


#include "Teuchos_PtrDecl.hpp"
#include "Teuchos_RCP.hpp"


namespace Teuchos {

#ifdef HAVE_TEUCHOSCORE_CXX11

template<class T, class Deleter=std::default_delete<T>>
class UniquePtr {
public:
inline UniquePtr( ENull null_in = null );

inline explicit UniquePtr( T *ptr_in );

inline UniquePtr( T *ptr_in,
typename std::conditional<std::is_reference<Deleter>::value,
Deleter, const Deleter&>::type d);

inline UniquePtr( T *ptr_in,
typename std::remove_reference<Deleter>::type &&d);

~UniquePtr();

// Copy constructor and assignment are disabled
inline UniquePtr(const UniquePtr<T>& ptr) = delete;
template<class U, class E>
inline UniquePtr(const UniquePtr<U, E>& ptr) = delete;
UniquePtr<T>& operator=(const UniquePtr<T>& ptr) = delete;
template<class U, class E>
UniquePtr<T>& operator=(const UniquePtr<U, E>& ptr) = delete;

// Move constructor and assignment
inline UniquePtr(UniquePtr &&r_ptr);

template<class U, class E>
inline UniquePtr(UniquePtr<U, E> &&r_ptr);

inline UniquePtr& operator=(UniquePtr &&r_ptr);

template<class U, class E>
inline UniquePtr& operator=(UniquePtr<U, E> &&r_ptr);


/*
* Modifiers
*/

inline T* release();

/** \brief Reset to r_ptr (default: null). */
inline void reset(T *r_ptr=nullptr);

inline void swap(UniquePtr & other) noexcept;

/*
* Observers
*/

/** \brief Get the raw C++ pointer to the underlying object. */
inline T* get() const;

inline Deleter& get_deleter() noexcept;

inline const Deleter& get_deleter() const noexcept;

inline explicit operator bool() const;

/*
* Dereferencing
*/

inline T* operator->() const;
inline T& operator*() const;

/*
* Observers Ptr
*/

/** \brief Return a Ptr<T> version of *this. */
inline Ptr<T> ptr() const;

/** \brief Return a Ptr<const T> version of *this. */
inline Ptr<const T> getConst() const;

/** \brief Shorthand for ptr(). */
inline Ptr<T> operator()() const;

/*
* Teuchos compatibility methods
*/

/** \brief Get the raw C++ pointer to the underlying object. */
inline T* getRawPtr() const;

/** \brief Returns true if the underlying pointer is null. */
inline bool is_null() const;

private:
typedef
#ifdef TEUCHOS_DEBUG
RCP<T>
#else
Ptr<T>
#endif
pointer;

std::tuple<pointer, Deleter> t_;
};

// -------------------------
// Non member functions

template<class T, class Deleter=std::default_delete<T>>
inline
UniquePtr<T, Deleter>
uniqueptr(T* p)
{
return UniquePtr<T>(p);
}

template<class T2, class T1, class Deleter=std::default_delete<T1>>
Ptr<T2> uniqueptr_implicit_cast(const UniquePtr<T1, Deleter>& p1)
{
return Ptr<T2>(p1.get()); // Will only compile if conversion is legal!
}

/** \brief Returns true if <tt>p.get()==NULL</tt>.
*
* \relates UniquePtr
*/
template<class T, class Deleter=std::default_delete<T>>
inline
bool is_null( const UniquePtr<T, Deleter> &p )
{
return !bool(p);
}

/** \brief Returns true if <tt>p.get()!=NULL</tt>
*
* \relates UniquePtr
*/
template<class T, class Deleter=std::default_delete<T>>
inline
bool nonnull( const UniquePtr<T, Deleter> &p )
{
return bool(p);
}


// --------------------------------
// Implementation of UniquePtr

template<class T, class Deleter>
inline UniquePtr<T, Deleter>::UniquePtr( ENull /*null_in*/ )
: t_(null, Deleter())
{}

template<class T, class Deleter>
inline UniquePtr<T, Deleter>::UniquePtr( T *ptr_in )
: t_(pointer(ptr_in), Deleter())
{}

template<class T, class Deleter>
inline UniquePtr<T, Deleter>::UniquePtr( T *ptr_in,
typename std::conditional<std::is_reference<Deleter>::value,
Deleter, const Deleter&>::type d)
: t_(pointer(ptr_in
#ifdef TEUCHOS_DEBUG
, deallocFunctorDelete<T, Deleter>(d), true
#endif
), d)
{}

template<class T, class Deleter>
inline UniquePtr<T, Deleter>::UniquePtr( T *ptr_in,
typename std::remove_reference<Deleter>::type &&d)
: t_(pointer(ptr_in
#ifdef TEUCHOS_DEBUG
, deallocFunctorDelete<T, Deleter>(d), true
#endif
), std::move(d))
{}

template<class T, class Deleter>
UniquePtr<T, Deleter>::~UniquePtr()
{
#ifndef TEUCHOS_DEBUG
get_deleter()(std::get<0>(t_).get()); // Note: the pointer can be null
#endif
}

template<class T, class Deleter>
inline UniquePtr<T, Deleter>::UniquePtr(UniquePtr &&r_ptr)
: t_(pointer(r_ptr.release()), std::forward<Deleter>(r_ptr.get_deleter()))
{}

template<class T, class Deleter>
template<class U, class E>
inline UniquePtr<T, Deleter>::UniquePtr(UniquePtr<U, E> &&r_ptr)
: t_(pointer(r_ptr.release()), std::forward<E>(r_ptr.get_deleter()))
{}

template<class T, class Deleter>
inline
Ptr<T> UniquePtr<T, Deleter>::ptr() const
{
return std::get<0>(t_).ptr();
}

template<class T, class Deleter>
inline
Ptr<T> UniquePtr<T, Deleter>::operator()() const
{
return ptr();
}

template<class T, class Deleter>
inline
UniquePtr<T, Deleter>& UniquePtr<T, Deleter>::operator=(UniquePtr<T, Deleter> &&r_ptr) {
reset(r_ptr.release());
get_deleter() = std::forward<Deleter>(r_ptr.get_deleter());
return *this;
}

template<class T, class Deleter>
template<class U, class E>
inline UniquePtr<T, Deleter>& UniquePtr<T, Deleter>::operator=(UniquePtr<U, E> &&r_ptr) {
reset(r_ptr.release());
get_deleter() = std::forward<E>(r_ptr.get_deleter());
return *this;
}

template<class T, class Deleter>
inline T* UniquePtr<T, Deleter>::release()
{
T *p = get();
#ifdef TEUCHOS_DEBUG
std::get<0>(t_).release(); // So that the next line does not delete the object
#endif
std::get<0>(t_) = null;
return p;
}

template<class T, class Deleter>
inline void UniquePtr<T, Deleter>::swap(UniquePtr & other) noexcept
{
std::swap(t_, other.t_);
}

template<class T, class Deleter>
inline
T* UniquePtr<T, Deleter>::get() const
{
return std::get<0>(t_).get();
}

template<class T, class Deleter>
inline
Deleter& UniquePtr<T, Deleter>::get_deleter() noexcept
{
return std::get<1>(t_);
}

template<class T, class Deleter>
inline
const Deleter& UniquePtr<T, Deleter>::get_deleter() const noexcept
{
return std::get<1>(t_);
}

template<class T, class Deleter>
inline
UniquePtr<T, Deleter>::operator bool() const
{
return get() != nullptr;
}

template<class T, class Deleter>
inline bool UniquePtr<T, Deleter>::is_null() const
{
return !bool(*this);
}

template<class T, class Deleter>
inline
T* UniquePtr<T, Deleter>::getRawPtr() const
{
return get();
}

template<class T, class Deleter>
inline
Ptr<const T> UniquePtr<T, Deleter>::getConst() const
{
return uniqueptr_implicit_cast<const T>(*this);
}

template<class T, class Deleter>
inline
T* UniquePtr<T, Deleter>::operator->() const
{
return std::get<0>(t_).operator->();
}

template<class T, class Deleter>
inline
T& UniquePtr<T, Deleter>::operator*() const {
return std::get<0>(t_).operator*();
}

template<class T, class Deleter>
inline
void UniquePtr<T, Deleter>::reset(T *r_ptr)
{
#ifdef TEUCHOS_DEBUG
std::get<0>(t_).reset();
std::get<0>(t_) = rcpWithDealloc(r_ptr, deallocFunctorDelete<T,
Deleter>(get_deleter()));
#else
get_deleter()(std::get<0>(t_).get()); // Note: the pointer can be null
std::get<0>(t_) = Ptr<T>(r_ptr);
#endif
}


#endif // HAVE_TEUCHOSCORE_CXX11


} // namespace Teuchos

#endif // TEUCHOS_UNIQUEPTR_HPP
7 changes: 7 additions & 0 deletions packages/teuchos/core/src/Teuchos_toString.hpp
Expand Up @@ -47,6 +47,13 @@

namespace Teuchos {

#ifdef HAVE_TEUCHOSCORE_CXX11
inline
std::ostream& operator<<(std::ostream& out, const std::nullptr_t)
{
return (out << "nullptr");
}
#endif

/** \brief Default traits class for converting objects into strings.
*
Expand Down