[Assorted-commits] SF.net SVN: assorted:[1219] cpp-commons/trunk
Brought to you by:
yangzhang
From: <yan...@us...> - 2009-02-22 06:49:49
|
Revision: 1219 http://assorted.svn.sourceforge.net/assorted/?rev=1219&view=rev Author: yangzhang Date: 2009-02-22 06:49:47 +0000 (Sun, 22 Feb 2009) Log Message: ----------- - moved a bunch of files around to get rid of the separation between boost-dependent and non-boost-dependent parts of the library - declared the library to require boost - removed libtask - updated the feature list - removed method_thread and other unnecessary thread utilities Modified Paths: -------------- cpp-commons/trunk/README cpp-commons/trunk/src/commons/array.h cpp-commons/trunk/src/commons/st/st.h cpp-commons/trunk/src/commons/threads.h Added Paths: ----------- cpp-commons/trunk/src/commons/delegates.h cpp-commons/trunk/src/commons/unique_ptr.hpp Removed Paths: ------------- cpp-commons/trunk/src/commons/boost/ cpp-commons/trunk/src/commons/task/ Modified: cpp-commons/trunk/README =================================================================== --- cpp-commons/trunk/README 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/README 2009-02-22 06:49:47 UTC (rev 1219) @@ -8,11 +8,13 @@ The C++ Commons is a general-purpose utility library for the C++ programming language. This is a library of header files, in the same spirit as [boost]. -Here are some of the features present in the library: +Features: - C functions for string manipulation - RAII utilities, such as for closing file descriptors and `finally` objects -- `array`: thin wrapper around arrays (`scoped_array` + size) +- smart arrays: sized arrays, "managed" (moveable, conditionally + scope-destroyed) arrays +- Howard Hinnant's C++03-emulated TR1 `unique_ptr.hpp` - `pool`: fixed-size object pools - bit manipulation - bundles of header includes @@ -35,14 +37,25 @@ - time utilities, including timers and simpler interfaces to system clocks - utilities for streams - utilities for [tamer] +- micro-utilities: noncopyable, expander annotations - x86 architecture-specific tools Setup ----- +Requirements: + +- [boost] 1.38.0 +- [GCC] 4 + Like [boost], just include these header files in your next C++ project, and you're ready to go! +Certain parts of the library have extra dependencies. (In particular, these +tend to be designed as supplementing the required libraries.) + +- [State Threads] 1.8 + Related Work ------------ Modified: cpp-commons/trunk/src/commons/array.h =================================================================== --- cpp-commons/trunk/src/commons/array.h 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/src/commons/array.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -1,10 +1,9 @@ #ifndef COMMONS_ARRAY_H #define COMMONS_ARRAY_H -#include <boost/scoped_array.hpp> -#include <commons/boost/unique_ptr.hpp> #include <commons/check.h> #include <commons/nullptr.h> +#include <commons/unique_ptr.hpp> #include <commons/utility.h> namespace commons { Copied: cpp-commons/trunk/src/commons/delegates.h (from rev 1216, cpp-commons/trunk/src/commons/boost/delegates.h) =================================================================== --- cpp-commons/trunk/src/commons/delegates.h (rev 0) +++ cpp-commons/trunk/src/commons/delegates.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -0,0 +1,69 @@ +#ifndef COMMONS_BOOST_DELEGATES_H +#define COMMONS_BOOST_DELEGATES_H + +#include <boost/function.hpp> +#include <boost/scoped_ptr.hpp> +#include <iostream> // for cerr + +namespace commons +{ + + using namespace boost; + using namespace std; + + typedef std::function<void()> fn; + + void + swallow(const fn f) { + try { f(); } + catch (std::exception &ex) { cerr << ex.what() << endl; } + } + + /** + * Delegate for running a 0-ary void function. + */ + void + run_function0(const void *p) + { + scoped_ptr<const fn> pf(reinterpret_cast<const fn*>(p)); + (*pf)(); + } + + /** + * NULL void*-returning delegate for running a 0-ary void function. + */ + void* + run_function0_null(void* p) + { + run_function0(p); + return NULL; + } + + // TODO: is there a way to do this? +// /** +// * Exception-returning delegate for running a 0-ary void function. +// */ +// void* +// run_function0_ex(void* p) +// { +// try { run_function0(p); } +// catch (std::exception &ex) { return std::exception(ex); } +// } + + /** + * A class that takes a functor and calls it on destruction, effectively + * giving you a `finally` clause. Particularly useful with clamp. + */ + //template<typename T> + typedef function0<void> T; + class finally { + public: + finally(T f): f_(f) {} + ~finally() { f_(); } + private: + T f_; + }; + +} + +#endif Property changes on: cpp-commons/trunk/src/commons/delegates.h ___________________________________________________________________ Added: svn:mergeinfo + Modified: cpp-commons/trunk/src/commons/st/st.h =================================================================== --- cpp-commons/trunk/src/commons/st/st.h 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/src/commons/st/st.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -10,10 +10,10 @@ #include <st.h> #include <stx.h> #include <commons/array.h> +#include <commons/delegates.h> #include <commons/nullptr.h> // delegates.h must be included after sockets.h due to bind() conflicts. #include <commons/sockets.h> -#include <commons/boost/delegates.h> #include <commons/utility.h> #include <boost/foreach.hpp> #include <boost/function.hpp> Modified: cpp-commons/trunk/src/commons/threads.h =================================================================== --- cpp-commons/trunk/src/commons/threads.h 2009-02-22 06:40:38 UTC (rev 1218) +++ cpp-commons/trunk/src/commons/threads.h 2009-02-22 06:49:47 UTC (rev 1219) @@ -6,11 +6,17 @@ #include <sys/types.h> #include <unistd.h> +#include <boost/function.hpp> + #include <commons/check.h> +#include <commons/delegates.h> +#include <commons/nullptr.h> namespace commons { + using namespace boost; + /** * Get the current thread ID. Glibc does not provide a wrapper for this * system call. @@ -41,171 +47,22 @@ waitall(pthread_t* ts, int n) { for (int i = 0; i < n; i++) { - check(pthread_join(ts[i], NULL) == 0); + check(pthread_join(ts[i], nullptr) == 0); } } /** - * Helper for launching new threads. - */ - void* - runner(void *p) - { - void (*f)() = (void(*)()) p; - (*f)(); - return NULL; - } - - /** * Run a function in pthread. * \return The new pthread_t on success, 0 on failure. * TODO: Is it safe to treat the pthread_t as an integral type? */ pthread_t - spawn(void (*f)()) + spawn(const boost::function<void()>& f) { pthread_t t; - return pthread_create(&t, NULL, &runner, (void*) f) == 0 ? t : 0; + return pthread_create(&t, NULL, &run_function0_null, (void*) new boost::function<void()>(f)) == 0 ? t : 0; } - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C> pthread_t - method_thread(C *o, void (C::*m)()) - { - class runnable { - public: - C *o; - void (C::*m)(); - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)() = r->m; - delete r; - (o->*m)(); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C, class A> pthread_t - method_thread(C *o, void (C::*m)(A), A a) - { - class runnable { - public: - C *o; - void (C::*m)(A a); - A a; - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)(A ) = r->m; - A a = r->a; - delete r; - (o->*m)(a); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - r->a = a; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C, class A1, class A2> pthread_t - method_thread(C *o, void (C::*m)(A1 , A2 ), A1 a1, A2 a2) - { - class runnable { - public: - C *o; - void (C::*m)(A1 a1, A2 a2); - A1 a1; - A2 a2; - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)(A1 , A2 ) = r->m; - A1 a1 = r->a1; - A2 a2 = r->a2; - delete r; - (o->*m)(a1, a2); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - r->a1 = a1; - r->a2 = a2; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - - /** - * Run a method in pthread. - * \return The new pthread_t on success, 0 on failure. - */ - template <class C, class A1, class A2, class A3> pthread_t - method_thread(C *o, void (C::*m)(A1 , A2, A3), A1 a1, A2 a2, A3 a3) - { - class runnable { - public: - C *o; - void (C::*m)(A1 a1, A2 a2, A3 a3); - A1 a1; - A2 a2; - A3 a3; - static void *run(void *vvv) { - runnable *r = (runnable*)vvv; - C *o = r->o; - void (C::*m)(A1, A2, A3) = r->m; - A1 a1 = r->a1; - A2 a2 = r->a2; - A3 a3 = r->a3; - delete r; - (o->*m)(a1, a2, a3); - return 0; - } - }; - runnable *r = new runnable; - r->o = o; - r->m = m; - r->a1 = a1; - r->a2 = a2; - r->a3 = a3; - pthread_t th; - if(pthread_create(&th, NULL, &runnable::run, (void *) r) == 0){ - return th; - } - return 0; - } - } #endif Copied: cpp-commons/trunk/src/commons/unique_ptr.hpp (from rev 1216, cpp-commons/trunk/src/commons/boost/unique_ptr.hpp) =================================================================== --- cpp-commons/trunk/src/commons/unique_ptr.hpp (rev 0) +++ cpp-commons/trunk/src/commons/unique_ptr.hpp 2009-02-22 06:49:47 UTC (rev 1219) @@ -0,0 +1,535 @@ +/////////////////////////////////////////////////////////////////////////////// +// unique_ptr.hpp header file +// +// Copyright 2009 Howard Hinnant, Ion Gaztañaga. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// See http://www.boost.org/libs/foreach for documentation + +// This is a C++03 emulation of std::unique_ptr placed in namespace boost. +// Reference http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf +// for the latest unique_ptr specification, and +// reference http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html +// for any pending issues against this specification. + +#ifndef UNIQUE_PTR_HPP +#define UNIQUE_PTR_HPP + +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits.hpp> +#include <boost/static_assert.hpp> +#include <boost/mpl/if.hpp> + +namespace boost +{ + +namespace detail_unique_ptr +{ + +typedef char one; +struct two {one _[2];}; + +// An is_convertible<From, To> that considers From an rvalue (consistent with C++0X). +// This is a simplified version neglecting the types function, array, void and abstract types +// I had to make a special case out of is_convertible<T,T> to make move-only +// types happy. + +namespace is_conv_imp +{ +template <class T> one test1(const T&); +template <class T> two test1(...); +template <class T> one test2(T); +template <class T> two test2(...); +template <class T> T source(); +} + +template <class T1, class T2> +struct is_convertible +{ + static const bool value = sizeof(is_conv_imp::test1<T2>(is_conv_imp::source<T1>())) == 1; +}; + +template <class T> +struct is_convertible<T, T> +{ + static const bool value = sizeof(is_conv_imp::test2<T>(is_conv_imp::source<T>())) == 1; +}; + +template <class T> +class rv +{ + T& r_; + +public: + explicit rv(T& r) : r_(r) {} + T* operator->() {return &r_;} + T& operator*() {return r_;} +}; + +template <class T> +struct identity +{ + typedef T type; +}; + +} // detail_unique_ptr + +template <class T> +inline +typename enable_if_c +< + !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + T& +>::type +move(T& t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + const T& +>::type +move(const T& t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value, + T +>::type +move(T& t) +{ + return T(detail_unique_ptr::rv<T>(t)); +} + +template <class T> +inline +typename enable_if_c +< + is_reference<T>::value, + T +>::type +forward(typename detail_unique_ptr::identity<T>::type t) +{ + return t; +} + +template <class T> +inline +typename enable_if_c +< + !is_reference<T>::value, + T +>::type +forward(typename detail_unique_ptr::identity<T>::type& t) +{ + return move(t); +} + +template <class T> +inline +typename enable_if_c +< + !is_reference<T>::value, + T +>::type +forward(const typename detail_unique_ptr::identity<T>::type& t) +{ + return move(const_cast<T&>(t)); +} + +namespace detail_unique_ptr { + +// A move-aware but stripped-down compressed_pair which only optimizes storage for T2 +template <class T1, class T2, bool = is_empty<T2>::value> +class unique_ptr_storage +{ + T1 t1_; + T2 t2_; + + typedef typename add_reference<T2>::type T2_reference; + typedef typename add_reference<const T2>::type T2_const_reference; + + unique_ptr_storage(const unique_ptr_storage&); + unique_ptr_storage& operator=(const unique_ptr_storage&); +public: + operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);} + + unique_ptr_storage() : t1_(), t2_() {} + + explicit unique_ptr_storage(T1 t1) + : t1_(move(t1)), t2_() {} + + unique_ptr_storage(T1 t1, T2 t2) + : t1_(move(t1)), t2_(forward<T2>(t2)) {} + + T1& first() {return t1_;} + const T1& first() const {return t1_;} + + T2_reference second() {return t2_;} + T2_const_reference second() const {return t2_;} +}; + +template <class T1, class T2> +class unique_ptr_storage<T1, T2, true> + : private T2 +{ + T1 t1_; + typedef T2 t2_; + + unique_ptr_storage(const unique_ptr_storage&); + unique_ptr_storage& operator=(const unique_ptr_storage&); +public: + operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);} + + unique_ptr_storage() : t1_() {} + + explicit unique_ptr_storage(T1 t1) + : t1_(move(t1)) {} + + unique_ptr_storage(T1 t1, T2 t2) + : t2_(move(t2)), t1_(move(t1)) {} + + T1& first() {return t1_;} + const T1& first() const {return t1_;} + + T2& second() {return *this;} + const T2& second() const {return *this;} +}; + +template <class T1, class T2, bool b> +inline +void +swap(unique_ptr_storage<T1, T2, b>& x, unique_ptr_storage<T1, T2, b>& y) +{ + using std::swap; + swap(x.first(), y.first()); + swap(x.second(), y.second()); +} + +} // detail_unique_ptr + +template <class T> +struct default_delete +{ + default_delete() {} + template <class U> + default_delete(const default_delete<U>&, + typename enable_if_c<detail_unique_ptr::is_convertible<U*, T*>::value>::type* = 0) + {} + + void operator()(T* ptr) const + { + BOOST_STATIC_ASSERT(sizeof(T) > 0); + delete ptr; + } +}; + +template <class T> +struct default_delete<T[]> +{ + void operator()(T* ptr) const + { + BOOST_STATIC_ASSERT(sizeof(T) > 0); + delete [] ptr; + } + +private: + + template <class U> void operator()(U*) const; +}; + +namespace detail_unique_ptr +{ + +namespace pointer_type_imp +{ + +template <class U> static two test(...); +template <class U> static one test(typename U::pointer* = 0); + +} // pointer_type_imp + +template <class T> +struct has_pointer_type +{ + static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1; +}; + +namespace pointer_type_imp +{ + +template <class T, class D, bool = has_pointer_type<D>::value> +struct pointer_type +{ + typedef typename D::pointer type; +}; + +template <class T, class D> +struct pointer_type<T, D, false> +{ + typedef T* type; +}; + +} // pointer_type_imp + +template <class T, class D> +struct pointer_type +{ + typedef typename pointer_type_imp::pointer_type<T, + typename boost::remove_reference<D>::type>::type type; +}; + +} // detail_unique_ptr + +template <class T, class D = default_delete<T> > +class unique_ptr +{ +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer; + +private: + detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_; + + typedef typename add_reference<deleter_type>::type deleter_reference; + typedef typename add_reference<const deleter_type>::type deleter_const_reference; + + struct nat {int for_bool_;}; + + unique_ptr(unique_ptr&); + unique_ptr& operator=(unique_ptr&); + +public: + operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);} + unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {} + unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r) + { + reset(r->release()); + ptr_.second() = move(r->get_deleter()); + return *this; + } + + unique_ptr() + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + explicit unique_ptr(pointer p) + : ptr_(p) + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + unique_ptr(pointer p, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type d) + : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {} + + template <class U, class E> + unique_ptr(unique_ptr<U, E> u, + typename enable_if_c + < + !boost::is_array<U>::value && + detail_unique_ptr::is_convertible<typename unique_ptr<U>::pointer, pointer>::value && + detail_unique_ptr::is_convertible<E, deleter_type>::value && + ( + !is_reference<deleter_type>::value || + is_same<deleter_type, E>::value + ) + >::type* = 0) + : ptr_(u.release(), forward<D>(forward<E>(u.get_deleter()))) {} + + ~unique_ptr() {reset();} + + unique_ptr& operator=(int nat::*) + { + reset(); + return *this; + } + + template <class U, class E> + unique_ptr& + operator=(unique_ptr<U, E> u) + { + reset(u.release()); + ptr_.second() = move(u.get_deleter()); + return *this; + } + + typename add_reference<T>::type operator*() const {return *get();} + pointer operator->() const {return get();} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} + + void reset(pointer p = pointer()) + { + pointer t = get(); + if (t != pointer()) + get_deleter()(t); + ptr_.first() = p; + } + + pointer release() + { + pointer tmp = get(); + ptr_.first() = pointer(); + return tmp; + } + + void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} +}; + +template <class T, class D> +class unique_ptr<T[], D> +{ +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer; + +private: + detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_; + + typedef typename add_reference<deleter_type>::type deleter_reference; + typedef typename add_reference<const deleter_type>::type deleter_const_reference; + + struct nat {int for_bool_;}; + + unique_ptr(unique_ptr&); + unique_ptr& operator=(unique_ptr&); + +public: + operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);} + unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {} + unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r) + { + reset(r->release()); + ptr_.second() = move(r->get_deleter()); + return *this; + } + + unique_ptr() + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + explicit unique_ptr(pointer p) + : ptr_(p) + { + BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value); + BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value); + } + + unique_ptr(pointer p, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type d) + : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {} + + ~unique_ptr() {reset();} + + T& operator[](size_t i) const {return get()[i];} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} + + void reset(pointer p = pointer()) + { + pointer t = get(); + if (t != pointer()) + get_deleter()(t); + ptr_.first() = p; + } + + pointer release() + { + pointer tmp = get(); + ptr_.first() = pointer(); + return tmp; + } + + void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);} +private: + template <class U> + explicit unique_ptr(U, + typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0); + + template <class U> + unique_ptr(U, typename mpl::if_<is_reference<D>, + volatile typename remove_reference<D>::type&, D>::type, + typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0); +}; + +template<class T, class D> +inline +void +swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) +{ + x.swap(y); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return x.get() == y.get(); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(x == y); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return x.get() < y.get(); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(y < x); +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return y < x; +} + +template<class T1, class D1, class T2, class D2> +inline +bool +operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) +{ + return !(x < y); +} + +} // boost + +#endif // UNIQUE_PTR_HPP Property changes on: cpp-commons/trunk/src/commons/unique_ptr.hpp ___________________________________________________________________ Added: svn:mergeinfo + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |