webrtc 使用scoped_ptr

来源:互联网 发布:品茗网络计划破解版 编辑:程序博客网 时间:2024/06/02 19:28
// Copyright (c) 2012 The Chromium Authors. All rights reserved.// Use of this source code is governed by a BSD-style license that can be// found in the LICENSE file.#ifndef THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_#define THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_// Macro with the boilerplate that makes a type move-only in C++03.//// USAGE//// This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create// a "move-only" type.  Unlike DISALLOW_COPY_AND_ASSIGN, this macro should be// the first line in a class declaration.//// A class using this macro must call .Pass() (or somehow be an r-value already)// before it can be:////   * Passed as a function argument//   * Used as the right-hand side of an assignment//   * Returned from a function//// Each class will still need to define their own "move constructor" and "move// operator=" to make this useful.  Here's an example of the macro, the move// constructor, and the move operator= from the scoped_ptr class:////  template <typename T>//  class scoped_ptr {//     TALK_MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)//   public://    scoped_ptr(RValue& other) : ptr_(other.release()) { }//    scoped_ptr& operator=(RValue& other) {//      swap(other);//      return *this;//    }//  };//// Note that the constructor must NOT be marked explicit.//// For consistency, the second parameter to the macro should always be RValue// unless you have a strong reason to do otherwise.  It is only exposed as a// macro parameter so that the move constructor and move operator= don't look// like they're using a phantom type.////// HOW THIS WORKS//// For a thorough explanation of this technique, see:////   http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor//// The summary is that we take advantage of 2 properties:////   1) non-const references will not bind to r-values.//   2) C++ can apply one user-defined conversion when initializing a//      variable.//// The first lets us disable the copy constructor and assignment operator// by declaring private version of them with a non-const reference parameter.//// For l-values, direct initialization still fails like in// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment// operators are private.//// For r-values, the situation is different. The copy constructor and// assignment operator are not viable due to (1), so we are trying to call// a non-existent constructor and non-existing operator= rather than a private// one.  Since we have not committed an error quite yet, we can provide an// alternate conversion sequence and a constructor.  We add////   * a private struct named "RValue"//   * a user-defined conversion "operator RValue()"//   * a "move constructor" and "move operator=" that take the RValue& as//     their sole parameter.//// Only r-values will trigger this sequence and execute our "move constructor"// or "move operator=."  L-values will match the private copy constructor and// operator= first giving a "private in this context" error.  This combination// gives us a move-only type.//// For signaling a destructive transfer of data from an l-value, we provide a// method named Pass() which creates an r-value for the current instance// triggering the move constructor or move operator=.//// Other ways to get r-values is to use the result of an expression like a// function call.//// Here's an example with comments explaining what gets triggered where:////    class Foo {//      TALK_MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue);////     public://       ... API ...//       Foo(RValue other);           // Move constructor.//       Foo& operator=(RValue rhs);  // Move operator=//    };////    Foo MakeFoo();  // Function that returns a Foo.////    Foo f;//    Foo f_copy(f);  // ERROR: Foo(Foo&) is private in this context.//    Foo f_assign;//    f_assign = f;   // ERROR: operator=(Foo&) is private in this context.//////    Foo f(MakeFoo());      // R-value so alternate conversion executed.//    Foo f_copy(f.Pass());  // R-value so alternate conversion executed.//    f = f_copy.Pass();     // R-value so alternate conversion executed.////// IMPLEMENTATION SUBTLETIES WITH RValue//// The RValue struct is just a container for a pointer back to the original// object. It should only ever be created as a temporary, and no external// class should ever declare it or use it in a parameter.//// It is tempting to want to use the RValue type in function parameters, but// excluding the limited usage here for the move constructor and move// operator=, doing so would mean that the function could take both r-values// and l-values equially which is unexpected.  See COMPARED To Boost.Move for// more details.//// An alternate, and incorrect, implementation of the RValue class used by// Boost.Move makes RValue a fieldless child of the move-only type. RValue&// is then used in place of RValue in the various operators.  The RValue& is// "created" by doing *reinterpret_cast<RValue*>(this).  This has the appeal// of never creating a temporary RValue struct even with optimizations// disabled.  Also, by virtue of inheritance you can treat the RValue// reference as if it were the move-only type itself.  Unfortunately,// using the result of this reinterpret_cast<> is actually undefined behavior// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer// will generate non-working code.//// In optimized builds, both implementations generate the same assembly so we// choose the one that adheres to the standard.////// COMPARED TO C++11//// In C++11, you would implement this functionality using an r-value reference// and our .Pass() method would be replaced with a call to std::move().//// This emulation also has a deficiency where it uses up the single// user-defined conversion allowed by C++ during initialization.  This can// cause problems in some API edge cases.  For instance, in scoped_ptr, it is// impossible to make a function "void Foo(scoped_ptr<Parent> p)" accept a// value of type scoped_ptr<Child> even if you add a constructor to// scoped_ptr<> that would make it look like it should work.  C++11 does not// have this deficiency.////// COMPARED TO Boost.Move//// Our implementation similar to Boost.Move, but we keep the RValue struct// private to the move-only type, and we don't use the reinterpret_cast<> hack.//// In Boost.Move, RValue is the boost::rv<> template.  This type can be used// when writing APIs like:////   void MyFunc(boost::rv<Foo>& f)//// that can take advantage of rv<> to avoid extra copies of a type.  However you// would still be able to call this version of MyFunc with an l-value:////   Foo f;//   MyFunc(f);  // Uh oh, we probably just destroyed |f| w/o calling Pass().//// unless someone is very careful to also declare a parallel override like:////   void MyFunc(const Foo& f)//// that would catch the l-values first.  This was declared unsafe in C++11 and// a C++11 compiler will explicitly fail MyFunc(f).  Unfortunately, we cannot// ensure this in C++03.//// Since we have no need for writing such APIs yet, our implementation keeps// RValue private and uses a .Pass() method to do the conversion instead of// trying to write a version of "std::move()." Writing an API like std::move()// would require the RValue struct to be public.////// CAVEATS//// If you include a move-only type as a field inside a class that does not// explicitly declare a copy constructor, the containing class's implicit// copy constructor will change from Containing(const Containing&) to// Containing(Containing&).  This can cause some unexpected errors.////   http://llvm.org/bugs/show_bug.cgi?id=11528//// The workaround is to explicitly declare your copy constructor.//#define TALK_MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \ private: \  struct rvalue_type { \    explicit rvalue_type(type* object) : object(object) {} \    type* object; \    }; \  type(type&); \  void operator=(type&); \ public: \  operator rvalue_type() { return rvalue_type(this); } \  type Pass() { return type(rvalue_type(this)); } \ private:#endif  // THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_

/**  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.**  Use of this source code is governed by a BSD-style license*  that can be found in the LICENSE file in the root of the source*  tree. An additional intellectual property rights grant can be found*  in the file PATENTS.  All contributing project authors may*  be found in the AUTHORS file in the root of the source tree.*/// Borrowed from Chromium's src/base/basictypes.h.#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_// The COMPILE_ASSERT macro can be used to verify that a compile time// expression is true. For example, you could use it to verify the// size of a static array:////   COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES,//                  content_type_names_incorrect_size);//// or to make sure a struct is smaller than a certain size:////   COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);//// The second argument to the macro is the name of the variable. If// the expression is false, most compilers will issue a warning/error// containing the name of the variable.// TODO(ajm): Hack to avoid multiple definitions until the base/ of webrtc and// libjingle are merged.#if !defined(COMPILE_ASSERT)template <bool>struct CompileAssert {};#define COMPILE_ASSERT(expr, msg) \  typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]#endif  // COMPILE_ASSERT#endif  // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_

#ifndef TALK_BASE_SCOPED_PTR_H__#define TALK_BASE_SCOPED_PTR_H__#include <cstddef>// for std::ptrdiff_t#include <stdlib.h>// for free() decl#include "compile_assert.h"// for COMPILE_ASSERT#include "move.h"// for TALK_MOVE_ONLY_TYPE_FOR_CPP_03#if !defined(WARN_UNUSED_RESULT)#if defined(__GNUC__)#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))#else#define WARN_UNUSED_RESULT#endif#endif  // WARN_UNUSED_RESULT#ifndef DISALLOW_ASSIGN#define DISALLOW_ASSIGN(TypeName) \  void operator=(const TypeName&)#endif#ifndef DISALLOW_COPY_AND_ASSIGN// A macro to disallow the evil copy constructor and operator= functions// This should be used in the private: declarations for a class#define DISALLOW_COPY_AND_ASSIGN(TypeName)    \  TypeName(const TypeName&);                    \  DISALLOW_ASSIGN(TypeName)#endif#ifdef _WIN32namespace std { using ::ptrdiff_t; };#endif // _WIN32namespace talk_base {// Function object which deletes its parameter, which must be a pointer.// If C is an array type, invokes 'delete[]' on the parameter; otherwise,// invokes 'delete'. The default deleter for scoped_ptr<T>.template <class T>struct DefaultDeleter {DefaultDeleter() {}template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {// IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor// if U* is implicitly convertible to T* and U is not an array type.//// Correct implementation should use SFINAE to disable this// constructor. However, since there are no other 1-argument constructors,// using a COMPILE_ASSERT() based on is_convertible<> and requiring// complete types is simpler and will cause compile failures for equivalent// misuses.//// Note, the is_convertible<U*, T*> check also ensures that U is not an// array. T is guaranteed to be a non-array, so any U* where U is an array// cannot convert to T*.enum { T_must_be_complete = sizeof(T) };enum { U_must_be_complete = sizeof(U) };COMPILE_ASSERT((talk_base::is_convertible<U*, T*>::value),U_ptr_must_implicitly_convert_to_T_ptr);}inline void operator()(T* ptr) const {enum { type_must_be_complete = sizeof(T) };delete ptr;}};// Specialization of DefaultDeleter for array types.template <class T>struct DefaultDeleter<T[]> {inline void operator()(T* ptr) const {enum { type_must_be_complete = sizeof(T) };delete[] ptr;}private:// Disable this operator for any U != T because it is undefined to execute// an array delete when the static type of the array mismatches the dynamic// type.//// References://   C++98 [expr.delete]p3//   http://cplusplus.github.com/LWG/lwg-defects.html#938template <typename U> void operator()(U* array) const;};template <class T, int n>struct DefaultDeleter<T[n]> {// Never allow someone to declare something like scoped_ptr<int[10]>.COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);};// Function object which invokes 'free' on its parameter, which must be// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr://// scoped_ptr<int, talk_base::FreeDeleter> foo_ptr(//     static_cast<int*>(malloc(sizeof(int))));struct FreeDeleter {inline void operator()(void* ptr) const {free(ptr);}};namespace internal {// Minimal implementation of the core logic of scoped_ptr, suitable for// reuse in both scoped_ptr and its specializations.template <class T, class D>class scoped_ptr_impl {public:explicit scoped_ptr_impl(T* p) : data_(p) { }// Initializer for deleters that have data parameters.scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}// Templated constructor that destructively takes the value from another// scoped_ptr_impl.template <typename U, typename V>scoped_ptr_impl(scoped_ptr_impl<U, V>* other): data_(other->release(), other->get_deleter()) {// We do not support move-only deleters.  We could modify our move// emulation to have talk_base::subtle::move() and// talk_base::subtle::forward()// functions that are imperfect emulations of their C++11 equivalents,// but until there's a requirement, just assume deleters are copyable.}template <typename U, typename V>void TakeState(scoped_ptr_impl<U, V>* other) {// See comment in templated constructor above regarding lack of support// for move-only deleters.reset(other->release());get_deleter() = other->get_deleter();}~scoped_ptr_impl() {if (data_.ptr != NULL) {// Not using get_deleter() saves one function call in non-optimized// builds.static_cast<D&>(data_)(data_.ptr);}}void reset(T* p) {// This is a self-reset, which is no longer allowed: http://crbug.com/162971if (p != NULL && p == data_.ptr)abort();// Note that running data_.ptr = p can lead to undefined behavior if// get_deleter()(get()) deletes this. In order to pevent this, reset()// should update the stored pointer before deleting its old value.//// However, changing reset() to use that behavior may cause current code to// break in unexpected ways. If the destruction of the owned object// dereferences the scoped_ptr when it is destroyed by a call to reset(),// then it will incorrectly dispatch calls to |p| rather than the original// value of |data_.ptr|.//// During the transition period, set the stored pointer to NULL while// deleting the object. Eventually, this safety check will be removed to// prevent the scenario initially described from occuring and// http://crbug.com/176091 can be closed.T* old = data_.ptr;data_.ptr = NULL;if (old != NULL)static_cast<D&>(data_)(old);data_.ptr = p;}T* get() const { return data_.ptr; }D& get_deleter() { return data_; }const D& get_deleter() const { return data_; }void swap(scoped_ptr_impl& p2) {// Standard swap idiom: 'using std::swap' ensures that std::swap is// present in the overload set, but we call swap unqualified so that// any more-specific overloads can be used, if available.using std::swap;swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));swap(data_.ptr, p2.data_.ptr);}T* release() {T* old_ptr = data_.ptr;data_.ptr = NULL;return old_ptr;}T** accept() {reset(NULL);return &(data_.ptr);}T** use() {return &(data_.ptr);}private:// Needed to allow type-converting constructor.template <typename U, typename V> friend class scoped_ptr_impl;// Use the empty base class optimization to allow us to have a D// member, while avoiding any space overhead for it when D is an// empty class.  See e.g. http://www.cantrip.org/emptyopt.html for a good// discussion of this technique.struct Data : public D {explicit Data(T* ptr_in) : ptr(ptr_in) {}Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}T* ptr;};Data data_;DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);};}  // namespace internal// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>// automatically deletes the pointer it holds (if any).// That is, scoped_ptr<T> owns the T object that it points to.// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.// Also like T*, scoped_ptr<T> is thread-compatible, and once you// dereference it, you get the thread safety guarantees of T.//// The size of scoped_ptr is small. On most compilers, when using the// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will// increase the size proportional to whatever state they need to have. See// comments inside scoped_ptr_impl<> for details.//// Current implementation targets having a strict subset of  C++11's// unique_ptr<> features. Known deficiencies include not supporting move-only// deleteres, function pointers as deleters, and deleters with reference// types.template <class T, class D = talk_base::DefaultDeleter<T> >class scoped_ptr {TALK_MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)public:// The element and deleter types.typedef T element_type;typedef D deleter_type;// Constructor.  Defaults to initializing with NULL.scoped_ptr() : impl_(NULL) { }// Constructor.  Takes ownership of p.explicit scoped_ptr(element_type* p) : impl_(p){ }// Constructor.  Allows initialization of a stateful deleter.scoped_ptr(element_type* p, const D& d) : impl_(p, d){}// Constructor.  Allows construction from a scoped_ptr rvalue for a// convertible type and deleter.//// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct// from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor// has different post-conditions if D is a reference type. Since this// implementation does not support deleters with reference type,// we do not need a separate move constructor allowing us to avoid one// use of SFINAE. You only need to care about this if you modify the// implementation of scoped_ptr.template <typename U, typename V>scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) {COMPILE_ASSERT(!talk_base::is_array<U>::value, U_cannot_be_an_array);}// Constructor.  Move constructor for C++03 move emulation of this type.scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }// operator=.  Allows assignment from a scoped_ptr rvalue for a convertible// type and deleter.//// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from// the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated// form has different requirements on for move-only Deleters. Since this// implementation does not support move-only Deleters, we do not need a// separate move assignment operator allowing us to avoid one use of SFINAE.// You only need to care about this if you modify the implementation of// scoped_ptr.template <typename U, typename V>scoped_ptr& operator=(scoped_ptr<U, V> rhs) {COMPILE_ASSERT(!talk_base::is_array<U>::value, U_cannot_be_an_array);impl_.TakeState(&rhs.impl_);return *this;}// Reset.  Deletes the currently owned object, if any.// Then takes ownership of a new object, if given.void reset(element_type* p = NULL) { impl_.reset(p); }// Accessors to get the owned object.// operator* and operator-> will assert() if there is no current object.element_type& operator*() const {ASSERT(impl_.get() != NULL);return *impl_.get();}element_type* operator->() const  {ASSERT(impl_.get() != NULL);return impl_.get();}element_type* get() const { return impl_.get(); }// Access to the deleter.deleter_type& get_deleter() { return impl_.get_deleter(); }const deleter_type& get_deleter() const { return impl_.get_deleter(); }// Allow scoped_ptr<element_type> to be used in boolean expressions, but not// implicitly convertible to a real bool (which is dangerous).//// Note that this trick is only safe when the == and != operators// are declared explicitly, as otherwise "scoped_ptr1 ==// scoped_ptr2" will compile but do the wrong thing (i.e., convert// to Testable and then do the comparison).private:typedef talk_base::internal::scoped_ptr_impl<element_type, deleter_type>scoped_ptr::*Testable;public:operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }// Comparison operators.// These return whether two scoped_ptr refer to the same object, not just to// two different but equal objects.bool operator==(const element_type* p) const { return impl_.get() == p; }bool operator!=(const element_type* p) const { return impl_.get() != p; }// Swap two scoped pointers.void swap(scoped_ptr& p2) {impl_.swap(p2.impl_);}// Release a pointer.// The return value is the current pointer held by this object.// If this object holds a NULL pointer, the return value is NULL.// After this operation, this object will hold a NULL pointer,// and will not own the object any more.element_type* release() WARN_UNUSED_RESULT{return impl_.release();}// Delete the currently held pointer and return a pointer// to allow overwriting of the current pointer address.element_type** accept() WARN_UNUSED_RESULT{return impl_.accept();}// Return a pointer to the current pointer address.element_type** use() WARN_UNUSED_RESULT{return impl_.use();}// C++98 doesn't support functions templates with default parameters which// makes it hard to write a PassAs() that understands converting the deleter// while preserving simple calling semantics.//// Until there is a use case for PassAs() with custom deleters, just ignore// the custom deleter.template <typename PassAsType>scoped_ptr<PassAsType> PassAs() {return scoped_ptr<PassAsType>(Pass());}private:// Needed to reach into |impl_| in the constructor.template <typename U, typename V> friend class scoped_ptr;talk_base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;// Forbidden for API compatibility with std::unique_ptr.explicit scoped_ptr(int disallow_construction_from_null);// Forbid comparison of scoped_ptr types.  If U != T, it totally// doesn't make sense, and if U == T, it still doesn't make sense// because you should never have the same object owned by two different// scoped_ptrs.template <class U> bool operator==(scoped_ptr<U> const& p2) const;template <class U> bool operator!=(scoped_ptr<U> const& p2) const;};}#endif  // #ifndef TALK_BASE_SCOPED_PTR_H__

#include "scoped_ptr.h"#include<iostream>#include<string>using namespace std;using namespace talk_base;class VoiceChannelTransport{public:VoiceChannelTransport(string s){name = s;}void Initialize(){cout << "Initialize" << endl;}private:string name;};int main(){{talk_base::scoped_ptr<VoiceChannelTransport> voice_channel_transport(new VoiceChannelTransport("abc"));voice_channel_transport.reset(new VoiceChannelTransport("cde"));voice_channel_transport.get()->Initialize();}cout << "Initialize" << endl;//error //VoiceChannelTransport * p = voice_channel_transport.get();//delete p;return 0;}




0 0
原创粉丝点击