Commit eba66ff5 authored by Kenton Varda's avatar Kenton Varda

Enable Own<const T> and Array<const T>.

parent 648839c3
...@@ -302,5 +302,26 @@ TEST(Array, HeapCopy) { ...@@ -302,5 +302,26 @@ TEST(Array, HeapCopy) {
} }
} }
TEST(Array, OwnConst) {
ArrayBuilder<int> builder = heapArrayBuilder<int>(2);
int x[2] = {123, 234};
builder.addAll(x, x + 2);
Array<int> i = builder.finish(); //heapArray<int>({123, 234});
ASSERT_EQ(2u, i.size());
EXPECT_EQ(123, i[0]);
EXPECT_EQ(234, i[1]);
Array<const int> ci = mv(i);
ASSERT_EQ(2u, ci.size());
EXPECT_EQ(123, ci[0]);
EXPECT_EQ(234, ci[1]);
Array<const int> ci2 = heapArray<const int>({345, 456});
ASSERT_EQ(2u, ci2.size());
EXPECT_EQ(345, ci2[0]);
EXPECT_EQ(456, ci2[1]);
}
} // namespace } // namespace
} // namespace kj } // namespace kj
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "common.h" #include "common.h"
#include <string.h> #include <string.h>
#include <initializer_list>
namespace kj { namespace kj {
...@@ -76,6 +77,12 @@ public: ...@@ -76,6 +77,12 @@ public:
other.ptr = nullptr; other.ptr = nullptr;
other.size_ = 0; other.size_ = 0;
} }
template <typename = EnableIfConst<T>>
inline Array(Array<RemoveConst<T>>&& other) noexcept
: ptr(other.ptr), size_(other.size_), disposer(other.disposer) {
other.ptr = nullptr;
other.size_ = 0;
}
inline Array(T* firstElement, size_t size, const ArrayDisposer& disposer) inline Array(T* firstElement, size_t size, const ArrayDisposer& disposer)
: ptr(firstElement), size_(size), disposer(&disposer) {} : ptr(firstElement), size_(size), disposer(&disposer) {}
...@@ -150,6 +157,9 @@ private: ...@@ -150,6 +157,9 @@ private:
disposer->dispose(ptrCopy, sizeCopy, sizeCopy); disposer->dispose(ptrCopy, sizeCopy, sizeCopy);
} }
} }
template <typename U>
friend class Array;
}; };
namespace internal { namespace internal {
...@@ -192,7 +202,8 @@ inline Array<T> heapArray(size_t size) { ...@@ -192,7 +202,8 @@ inline Array<T> heapArray(size_t size) {
template <typename T> Array<T> heapArray(const T* content, size_t size); template <typename T> Array<T> heapArray(const T* content, size_t size);
template <typename T> Array<T> heapArray(ArrayPtr<const T> content); template <typename T> Array<T> heapArray(ArrayPtr<const T> content);
template <typename T, typename Iterator> Array<T> heapArray(Iterator begin, Iterator end); template <typename T, typename Iterator> Array<T> heapArray(Iterator begin, Iterator end);
// Allocate a heap arary containing a copy of the given content. template <typename T> Array<T> heapArray(std::initializer_list<T> init);
// Allocate a heap array containing a copy of the given content.
template <typename T, typename Container> template <typename T, typename Container>
Array<T> heapArrayFromIterable(Container&& a) { return heapArray(a.begin(), a.end()); } Array<T> heapArrayFromIterable(Container&& a) { return heapArray(a.begin(), a.end()); }
...@@ -210,7 +221,8 @@ class ArrayBuilder { ...@@ -210,7 +221,8 @@ class ArrayBuilder {
public: public:
ArrayBuilder(): ptr(nullptr), pos(nullptr), endPtr(nullptr) {} ArrayBuilder(): ptr(nullptr), pos(nullptr), endPtr(nullptr) {}
ArrayBuilder(decltype(nullptr)): ptr(nullptr), pos(nullptr), endPtr(nullptr) {} ArrayBuilder(decltype(nullptr)): ptr(nullptr), pos(nullptr), endPtr(nullptr) {}
explicit ArrayBuilder(T* firstElement, size_t capacity, const ArrayDisposer& disposer) explicit ArrayBuilder(RemoveConst<T>* firstElement, size_t capacity,
const ArrayDisposer& disposer)
: ptr(firstElement), pos(firstElement), endPtr(firstElement + capacity), : ptr(firstElement), pos(firstElement), endPtr(firstElement + capacity),
disposer(&disposer) {} disposer(&disposer) {}
ArrayBuilder(ArrayBuilder&& other) ArrayBuilder(ArrayBuilder&& other)
...@@ -296,7 +308,7 @@ public: ...@@ -296,7 +308,7 @@ public:
private: private:
T* ptr; T* ptr;
T* pos; RemoveConst<T>* pos;
T* endPtr; T* endPtr;
const ArrayDisposer* disposer; const ArrayDisposer* disposer;
...@@ -320,8 +332,8 @@ inline ArrayBuilder<T> heapArrayBuilder(size_t size) { ...@@ -320,8 +332,8 @@ inline ArrayBuilder<T> heapArrayBuilder(size_t size) {
// Like `heapArray<T>()` but does not default-construct the elements. You must construct them // Like `heapArray<T>()` but does not default-construct the elements. You must construct them
// manually by calling `add()`. // manually by calling `add()`.
return ArrayBuilder<T>(internal::HeapArrayDisposer::allocateUninitialized<T>(size), size, return ArrayBuilder<T>(internal::HeapArrayDisposer::allocateUninitialized<RemoveConst<T>>(size),
internal::HeapArrayDisposer::instance); size, internal::HeapArrayDisposer::instance);
} }
// ======================================================================================= // =======================================================================================
...@@ -392,7 +404,8 @@ template <typename T> ...@@ -392,7 +404,8 @@ template <typename T>
struct ArrayDisposer::Dispose_<T, true> { struct ArrayDisposer::Dispose_<T, true> {
static void dispose(T* firstElement, size_t elementCount, size_t capacity, static void dispose(T* firstElement, size_t elementCount, size_t capacity,
const ArrayDisposer& disposer) { const ArrayDisposer& disposer) {
disposer.disposeImpl(firstElement, sizeof(T), elementCount, capacity, nullptr); disposer.disposeImpl(const_cast<RemoveConst<T>*>(firstElement),
sizeof(T), elementCount, capacity, nullptr);
} }
}; };
template <typename T> template <typename T>
...@@ -462,7 +475,7 @@ struct CopyConstructArray_; ...@@ -462,7 +475,7 @@ struct CopyConstructArray_;
template <typename T> template <typename T>
struct CopyConstructArray_<T, T*, true> { struct CopyConstructArray_<T, T*, true> {
static inline T* apply(T* __restrict__ pos, T* start, T* end) { static inline T* apply(T* __restrict__ pos, T* start, T* end) {
memcpy(pos, start, end - start); memcpy(pos, start, reinterpret_cast<byte*>(end) - reinterpret_cast<byte*>(start));
return pos + (end - start); return pos + (end - start);
} }
}; };
...@@ -470,7 +483,7 @@ struct CopyConstructArray_<T, T*, true> { ...@@ -470,7 +483,7 @@ struct CopyConstructArray_<T, T*, true> {
template <typename T> template <typename T>
struct CopyConstructArray_<T, const T*, true> { struct CopyConstructArray_<T, const T*, true> {
static inline T* apply(T* __restrict__ pos, const T* start, const T* end) { static inline T* apply(T* __restrict__ pos, const T* start, const T* end) {
memcpy(pos, start, end - start); memcpy(pos, start, reinterpret_cast<const byte*>(end) - reinterpret_cast<const byte*>(start));
return pos + (end - start); return pos + (end - start);
} }
}; };
...@@ -554,6 +567,11 @@ heapArray(Iterator begin, Iterator end) { ...@@ -554,6 +567,11 @@ heapArray(Iterator begin, Iterator end) {
return builder.finish(); return builder.finish();
} }
template <typename T>
inline Array<T> heapArray(std::initializer_list<T> init) {
return heapArray<T>(init.begin(), init.end());
}
} // namespace kj } // namespace kj
#endif // KJ_ARRAY_H_ #endif // KJ_ARRAY_H_
...@@ -176,6 +176,10 @@ template <typename T> struct RemoveReference_ { typedef T Type; }; ...@@ -176,6 +176,10 @@ template <typename T> struct RemoveReference_ { typedef T Type; };
template <typename T> struct RemoveReference_<T&> { typedef T Type; }; template <typename T> struct RemoveReference_<T&> { typedef T Type; };
template <typename T> using RemoveReference = typename RemoveReference_<T>::Type; template <typename T> using RemoveReference = typename RemoveReference_<T>::Type;
template <typename T> struct RemoveConst_ { typedef T Type; };
template <typename T> struct RemoveConst_<const T> { typedef T Type; };
template <typename T> using RemoveConst = typename RemoveConst_<T>::Type;
template <typename> struct IsLvalueReference_ { static constexpr bool value = false; }; template <typename> struct IsLvalueReference_ { static constexpr bool value = false; };
template <typename T> struct IsLvalueReference_<T&> { static constexpr bool value = true; }; template <typename T> struct IsLvalueReference_<T&> { static constexpr bool value = true; };
template <typename T> template <typename T>
......
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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.
#include "memory.h"
#include <gtest/gtest.h>
#include "debug.h"
namespace kj {
namespace {
TEST(Memory, OwnConst) {
Own<int> i = heap<int>(2);
EXPECT_EQ(2, *i);
Own<const int> ci = mv(i);
EXPECT_EQ(2, *ci);
Own<const int> ci2 = heap<const int>(3);
EXPECT_EQ(3, *ci2);
}
// TODO(test): More tests.
} // namespace
} // namespace kj
...@@ -88,6 +88,9 @@ public: ...@@ -88,6 +88,9 @@ public:
Own(const Own& other) = delete; Own(const Own& other) = delete;
inline Own(Own&& other) noexcept inline Own(Own&& other) noexcept
: disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; } : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
template <typename = EnableIfConst<T>>
inline Own(Own<RemoveConst<T>>&& other) noexcept
: disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
template <typename U> template <typename U>
inline Own(Own<U>&& other) noexcept inline Own(Own<U>&& other) noexcept
: disposer(other.disposer), ptr(other.ptr) { : disposer(other.disposer), ptr(other.ptr) {
...@@ -126,9 +129,12 @@ private: ...@@ -126,9 +129,12 @@ private:
T* ptrCopy = ptr; T* ptrCopy = ptr;
if (ptrCopy != nullptr) { if (ptrCopy != nullptr) {
ptr = nullptr; ptr = nullptr;
disposer->dispose(ptrCopy); disposer->dispose(const_cast<RemoveConst<T>*>(ptrCopy));
} }
} }
template <typename U>
friend class Own;
}; };
namespace internal { namespace internal {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment