diff options
author | Brian Carlstrom <bdc@google.com> | 2013-05-10 21:52:02 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2013-05-10 21:52:02 +0000 |
commit | 9577926537ea6668ec4ade67d5758f871e9e5fb3 (patch) | |
tree | c884b048d310c9e82accb80eff6b522da81e1ede | |
parent | 66e1bcb78a04c4d75bc12940e81418d815ae2a2d (diff) | |
parent | 3d9d2148155c2e0b3bf51cd548f58f93d1199a4e (diff) | |
download | android_libnativehelper-9577926537ea6668ec4ade67d5758f871e9e5fb3.tar.gz android_libnativehelper-9577926537ea6668ec4ade67d5758f871e9e5fb3.tar.bz2 android_libnativehelper-9577926537ea6668ec4ade67d5758f871e9e5fb3.zip |
Merge "Move more utility classes from libcore to libnativehelper (part 1)"
-rw-r--r-- | include/nativehelper/ScopedBytes.h | 80 | ||||
-rw-r--r-- | include/nativehelper/ScopedLocalFrame.h | 40 | ||||
-rw-r--r-- | include/nativehelper/ScopedLocalRef.h | 63 | ||||
-rw-r--r-- | include/nativehelper/ScopedPrimitiveArray.h | 110 | ||||
-rw-r--r-- | include/nativehelper/ScopedStringChars.h | 74 | ||||
-rw-r--r-- | include/nativehelper/ScopedUtfChars.h | 71 | ||||
-rw-r--r-- | include/nativehelper/UniquePtr.h | 231 |
7 files changed, 669 insertions, 0 deletions
diff --git a/include/nativehelper/ScopedBytes.h b/include/nativehelper/ScopedBytes.h new file mode 100644 index 0000000..cb2614b --- /dev/null +++ b/include/nativehelper/ScopedBytes.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed 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 SCOPED_BYTES_H_included +#define SCOPED_BYTES_H_included + +#include "JNIHelp.h" + +/** + * ScopedBytesRO and ScopedBytesRW attempt to paper over the differences between byte[]s and + * ByteBuffers. This in turn helps paper over the differences between non-direct ByteBuffers backed + * by byte[]s, direct ByteBuffers backed by bytes[]s, and direct ByteBuffers not backed by byte[]s. + * (On Android, this last group only contains MappedByteBuffers.) + */ +template<bool readOnly> +class ScopedBytes { +public: + ScopedBytes(JNIEnv* env, jobject object) + : mEnv(env), mObject(object), mByteArray(NULL), mPtr(NULL) + { + if (mObject == NULL) { + jniThrowNullPointerException(mEnv, NULL); + } else if (mEnv->IsInstanceOf(mObject, JniConstants::byteArrayClass)) { + mByteArray = reinterpret_cast<jbyteArray>(mObject); + mPtr = mEnv->GetByteArrayElements(mByteArray, NULL); + } else { + mPtr = reinterpret_cast<jbyte*>(mEnv->GetDirectBufferAddress(mObject)); + } + } + + ~ScopedBytes() { + if (mByteArray != NULL) { + mEnv->ReleaseByteArrayElements(mByteArray, mPtr, readOnly ? JNI_ABORT : 0); + } + } + +private: + JNIEnv* mEnv; + jobject mObject; + jbyteArray mByteArray; + +protected: + jbyte* mPtr; + +private: + // Disallow copy and assignment. + ScopedBytes(const ScopedBytes&); + void operator=(const ScopedBytes&); +}; + +class ScopedBytesRO : public ScopedBytes<true> { +public: + ScopedBytesRO(JNIEnv* env, jobject object) : ScopedBytes<true>(env, object) {} + const jbyte* get() const { + return mPtr; + } +}; + +class ScopedBytesRW : public ScopedBytes<false> { +public: + ScopedBytesRW(JNIEnv* env, jobject object) : ScopedBytes<false>(env, object) {} + jbyte* get() { + return mPtr; + } +}; + +#endif // SCOPED_BYTES_H_included diff --git a/include/nativehelper/ScopedLocalFrame.h b/include/nativehelper/ScopedLocalFrame.h new file mode 100644 index 0000000..35b6ad8 --- /dev/null +++ b/include/nativehelper/ScopedLocalFrame.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed 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 SCOPED_LOCAL_FRAME_H_included +#define SCOPED_LOCAL_FRAME_H_included + +#include "JNIHelp.h" + +class ScopedLocalFrame { +public: + ScopedLocalFrame(JNIEnv* env) : mEnv(env) { + mEnv->PushLocalFrame(128); + } + + ~ScopedLocalFrame() { + mEnv->PopLocalFrame(NULL); + } + +private: + JNIEnv* mEnv; + + // Disallow copy and assignment. + ScopedLocalFrame(const ScopedLocalFrame&); + void operator=(const ScopedLocalFrame&); +}; + +#endif // SCOPED_LOCAL_FRAME_H_included diff --git a/include/nativehelper/ScopedLocalRef.h b/include/nativehelper/ScopedLocalRef.h new file mode 100644 index 0000000..71d5776 --- /dev/null +++ b/include/nativehelper/ScopedLocalRef.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed 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 SCOPED_LOCAL_REF_H_included +#define SCOPED_LOCAL_REF_H_included + +#include "jni.h" + +#include <stddef.h> + +// A smart pointer that deletes a JNI local reference when it goes out of scope. +template<typename T> +class ScopedLocalRef { +public: + ScopedLocalRef(JNIEnv* env, T localRef) : mEnv(env), mLocalRef(localRef) { + } + + ~ScopedLocalRef() { + reset(); + } + + void reset(T ptr = NULL) { + if (ptr != mLocalRef) { + if (mLocalRef != NULL) { + mEnv->DeleteLocalRef(mLocalRef); + } + mLocalRef = ptr; + } + } + + T release() __attribute__((warn_unused_result)) { + T localRef = mLocalRef; + mLocalRef = NULL; + return localRef; + } + + T get() const { + return mLocalRef; + } + +private: + JNIEnv* mEnv; + T mLocalRef; + + // Disallow copy and assignment. + ScopedLocalRef(const ScopedLocalRef&); + void operator=(const ScopedLocalRef&); +}; + +#endif // SCOPED_LOCAL_REF_H_included diff --git a/include/nativehelper/ScopedPrimitiveArray.h b/include/nativehelper/ScopedPrimitiveArray.h new file mode 100644 index 0000000..f6626b2 --- /dev/null +++ b/include/nativehelper/ScopedPrimitiveArray.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed 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 SCOPED_PRIMITIVE_ARRAY_H_included +#define SCOPED_PRIMITIVE_ARRAY_H_included + +#include "JNIHelp.h" + +// ScopedBooleanArrayRO, ScopedByteArrayRO, ScopedCharArrayRO, ScopedDoubleArrayRO, +// ScopedFloatArrayRO, ScopedIntArrayRO, ScopedLongArrayRO, and ScopedShortArrayRO provide +// convenient read-only access to Java arrays from JNI code. This is cheaper than read-write +// access and should be used by default. +#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(PRIMITIVE_TYPE, NAME) \ + class Scoped ## NAME ## ArrayRO { \ + public: \ + Scoped ## NAME ## ArrayRO(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \ + : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \ + if (mJavaArray == NULL) { \ + jniThrowNullPointerException(mEnv, NULL); \ + } else { \ + mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \ + } \ + } \ + ~Scoped ## NAME ## ArrayRO() { \ + if (mRawArray) { \ + mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, JNI_ABORT); \ + } \ + } \ + const PRIMITIVE_TYPE* get() const { return mRawArray; } \ + PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \ + const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \ + size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \ + private: \ + JNIEnv* mEnv; \ + PRIMITIVE_TYPE ## Array mJavaArray; \ + PRIMITIVE_TYPE* mRawArray; \ + Scoped ## NAME ## ArrayRO(const Scoped ## NAME ## ArrayRO&); \ + void operator=(const Scoped ## NAME ## ArrayRO&); \ + } + +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jboolean, Boolean); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jbyte, Byte); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jchar, Char); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jdouble, Double); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jfloat, Float); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jint, Int); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jlong, Long); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short); + +#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO + +// ScopedBooleanArrayRW, ScopedByteArrayRW, ScopedCharArrayRW, ScopedDoubleArrayRW, +// ScopedFloatArrayRW, ScopedIntArrayRW, ScopedLongArrayRW, and ScopedShortArrayRW provide +// convenient read-write access to Java arrays from JNI code. These are more expensive, +// since they entail a copy back onto the Java heap, and should only be used when necessary. +#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(PRIMITIVE_TYPE, NAME) \ + class Scoped ## NAME ## ArrayRW { \ + public: \ + Scoped ## NAME ## ArrayRW(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \ + : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \ + if (mJavaArray == NULL) { \ + jniThrowNullPointerException(mEnv, NULL); \ + } else { \ + mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \ + } \ + } \ + ~Scoped ## NAME ## ArrayRW() { \ + if (mRawArray) { \ + mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, 0); \ + } \ + } \ + const PRIMITIVE_TYPE* get() const { return mRawArray; } \ + PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \ + const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \ + PRIMITIVE_TYPE* get() { return mRawArray; } \ + PRIMITIVE_TYPE& operator[](size_t n) { return mRawArray[n]; } \ + size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \ + private: \ + JNIEnv* mEnv; \ + PRIMITIVE_TYPE ## Array mJavaArray; \ + PRIMITIVE_TYPE* mRawArray; \ + Scoped ## NAME ## ArrayRW(const Scoped ## NAME ## ArrayRW&); \ + void operator=(const Scoped ## NAME ## ArrayRW&); \ + } + +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jboolean, Boolean); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jbyte, Byte); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jchar, Char); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jdouble, Double); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jfloat, Float); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jint, Int); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jlong, Long); +INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jshort, Short); + +#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW + +#endif // SCOPED_PRIMITIVE_ARRAY_H_included diff --git a/include/nativehelper/ScopedStringChars.h b/include/nativehelper/ScopedStringChars.h new file mode 100644 index 0000000..cfbd247 --- /dev/null +++ b/include/nativehelper/ScopedStringChars.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed 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 SCOPED_STRING_CHARS_H_included +#define SCOPED_STRING_CHARS_H_included + +#include "JNIHelp.h" + +// A smart pointer that provides access to a jchar* given a JNI jstring. +// Unlike GetStringChars, we throw NullPointerException rather than abort if +// passed a null jstring, and get will return NULL. +// This makes the correct idiom very simple: +// +// ScopedStringChars name(env, java_name); +// if (name.get() == NULL) { +// return NULL; +// } +class ScopedStringChars { + public: + ScopedStringChars(JNIEnv* env, jstring s) : env_(env), string_(s), size_(0) { + if (s == NULL) { + chars_ = NULL; + jniThrowNullPointerException(env, NULL); + } else { + chars_ = env->GetStringChars(string_, NULL); + if (chars_ != NULL) { + size_ = env->GetStringLength(string_); + } + } + } + + ~ScopedStringChars() { + if (chars_ != NULL) { + env_->ReleaseStringChars(string_, chars_); + } + } + + const jchar* get() const { + return chars_; + } + + size_t size() const { + return size_; + } + + const jchar& operator[](size_t n) const { + return chars_[n]; + } + + private: + JNIEnv* env_; + jstring string_; + const jchar* chars_; + size_t size_; + + // Disallow copy and assignment. + ScopedStringChars(const ScopedStringChars&); + void operator=(const ScopedStringChars&); +}; + +#endif // SCOPED_STRING_CHARS_H_included diff --git a/include/nativehelper/ScopedUtfChars.h b/include/nativehelper/ScopedUtfChars.h new file mode 100644 index 0000000..7761450 --- /dev/null +++ b/include/nativehelper/ScopedUtfChars.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed 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 SCOPED_UTF_CHARS_H_included +#define SCOPED_UTF_CHARS_H_included + +#include "JNIHelp.h" +#include <string.h> + +// A smart pointer that provides read-only access to a Java string's UTF chars. +// Unlike GetStringUTFChars, we throw NullPointerException rather than abort if +// passed a null jstring, and c_str will return NULL. +// This makes the correct idiom very simple: +// +// ScopedUtfChars name(env, java_name); +// if (name.c_str() == NULL) { +// return NULL; +// } +class ScopedUtfChars { + public: + ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) { + if (s == NULL) { + utf_chars_ = NULL; + jniThrowNullPointerException(env, NULL); + } else { + utf_chars_ = env->GetStringUTFChars(s, NULL); + } + } + + ~ScopedUtfChars() { + if (utf_chars_) { + env_->ReleaseStringUTFChars(string_, utf_chars_); + } + } + + const char* c_str() const { + return utf_chars_; + } + + size_t size() const { + return strlen(utf_chars_); + } + + const char& operator[](size_t n) const { + return utf_chars_[n]; + } + + private: + JNIEnv* env_; + jstring string_; + const char* utf_chars_; + + // Disallow copy and assignment. + ScopedUtfChars(const ScopedUtfChars&); + void operator=(const ScopedUtfChars&); +}; + +#endif // SCOPED_UTF_CHARS_H_included diff --git a/include/nativehelper/UniquePtr.h b/include/nativehelper/UniquePtr.h new file mode 100644 index 0000000..31db377 --- /dev/null +++ b/include/nativehelper/UniquePtr.h @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed 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 UNIQUE_PTR_H_included +#define UNIQUE_PTR_H_included + +#include <cstdlib> // For NULL. + +// Default deleter for pointer types. +template <typename T> +struct DefaultDelete { + enum { type_must_be_complete = sizeof(T) }; + DefaultDelete() {} + void operator()(T* p) const { + delete p; + } +}; + +// Default deleter for array types. +template <typename T> +struct DefaultDelete<T[]> { + enum { type_must_be_complete = sizeof(T) }; + void operator()(T* p) const { + delete[] p; + } +}; + +// A smart pointer that deletes the given pointer on destruction. +// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr +// and boost::scoped_array). +// Named to be in keeping with Android style but also to avoid +// collision with any other implementation, until we can switch over +// to unique_ptr. +// Use thus: +// UniquePtr<C> c(new C); +template <typename T, typename D = DefaultDelete<T> > +class UniquePtr { +public: + // Construct a new UniquePtr, taking ownership of the given raw pointer. + explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) { + } + + ~UniquePtr() { + reset(); + } + + // Accessors. + T& operator*() const { return *mPtr; } + T* operator->() const { return mPtr; } + T* get() const { return mPtr; } + + // Returns the raw pointer and hands over ownership to the caller. + // The pointer will not be deleted by UniquePtr. + T* release() __attribute__((warn_unused_result)) { + T* result = mPtr; + mPtr = NULL; + return result; + } + + // Takes ownership of the given raw pointer. + // If this smart pointer previously owned a different raw pointer, that + // raw pointer will be freed. + void reset(T* ptr = NULL) { + if (ptr != mPtr) { + D()(mPtr); + mPtr = ptr; + } + } + +private: + // The raw pointer. + T* mPtr; + + // Comparing unique pointers is probably a mistake, since they're unique. + template <typename T2> bool operator==(const UniquePtr<T2>& p) const; + template <typename T2> bool operator!=(const UniquePtr<T2>& p) const; + + // Disallow copy and assignment. + UniquePtr(const UniquePtr&); + void operator=(const UniquePtr&); +}; + +// Partial specialization for array types. Like std::unique_ptr, this removes +// operator* and operator-> but adds operator[]. +template <typename T, typename D> +class UniquePtr<T[], D> { +public: + explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) { + } + + ~UniquePtr() { + reset(); + } + + T& operator[](size_t i) const { + return mPtr[i]; + } + T* get() const { return mPtr; } + + T* release() __attribute__((warn_unused_result)) { + T* result = mPtr; + mPtr = NULL; + return result; + } + + void reset(T* ptr = NULL) { + if (ptr != mPtr) { + D()(mPtr); + mPtr = ptr; + } + } + +private: + T* mPtr; + + // Disallow copy and assignment. + UniquePtr(const UniquePtr&); + void operator=(const UniquePtr&); +}; + +#if UNIQUE_PTR_TESTS + +// Run these tests with: +// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out + +#include <stdio.h> + +static void assert(bool b) { + if (!b) { + fprintf(stderr, "FAIL\n"); + abort(); + } + fprintf(stderr, "OK\n"); +} +static int cCount = 0; +struct C { + C() { ++cCount; } + ~C() { --cCount; } +}; +static bool freed = false; +struct Freer { + void operator()(int* p) { + assert(*p == 123); + free(p); + freed = true; + } +}; + +int main(int argc, char* argv[]) { + // + // UniquePtr<T> tests... + // + + // Can we free a single object? + { + UniquePtr<C> c(new C); + assert(cCount == 1); + } + assert(cCount == 0); + // Does release work? + C* rawC; + { + UniquePtr<C> c(new C); + assert(cCount == 1); + rawC = c.release(); + } + assert(cCount == 1); + delete rawC; + // Does reset work? + { + UniquePtr<C> c(new C); + assert(cCount == 1); + c.reset(new C); + assert(cCount == 1); + } + assert(cCount == 0); + + // + // UniquePtr<T[]> tests... + // + + // Can we free an array? + { + UniquePtr<C[]> cs(new C[4]); + assert(cCount == 4); + } + assert(cCount == 0); + // Does release work? + { + UniquePtr<C[]> c(new C[4]); + assert(cCount == 4); + rawC = c.release(); + } + assert(cCount == 4); + delete[] rawC; + // Does reset work? + { + UniquePtr<C[]> c(new C[4]); + assert(cCount == 4); + c.reset(new C[2]); + assert(cCount == 2); + } + assert(cCount == 0); + + // + // Custom deleter tests... + // + assert(!freed); + { + UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int)))); + *i = 123; + } + assert(freed); + return 0; +} +#endif + +#endif // UNIQUE_PTR_H_included |