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) {
}
}
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 kj
......@@ -26,6 +26,7 @@
#include "common.h"
#include <string.h>
#include <initializer_list>
namespace kj {
......@@ -76,6 +77,12 @@ public:
other.ptr = nullptr;
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)
: ptr(firstElement), size_(size), disposer(&disposer) {}
......@@ -150,6 +157,9 @@ private:
disposer->dispose(ptrCopy, sizeCopy, sizeCopy);
}
}
template <typename U>
friend class Array;
};
namespace internal {
......@@ -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(ArrayPtr<const T> content);
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>
Array<T> heapArrayFromIterable(Container&& a) { return heapArray(a.begin(), a.end()); }
......@@ -210,7 +221,8 @@ class ArrayBuilder {
public:
ArrayBuilder(): 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),
disposer(&disposer) {}
ArrayBuilder(ArrayBuilder&& other)
......@@ -296,7 +308,7 @@ public:
private:
T* ptr;
T* pos;
RemoveConst<T>* pos;
T* endPtr;
const ArrayDisposer* disposer;
......@@ -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
// manually by calling `add()`.
return ArrayBuilder<T>(internal::HeapArrayDisposer::allocateUninitialized<T>(size), size,
internal::HeapArrayDisposer::instance);
return ArrayBuilder<T>(internal::HeapArrayDisposer::allocateUninitialized<RemoveConst<T>>(size),
size, internal::HeapArrayDisposer::instance);
}
// =======================================================================================
......@@ -392,7 +404,8 @@ template <typename T>
struct ArrayDisposer::Dispose_<T, true> {
static void dispose(T* firstElement, size_t elementCount, size_t capacity,
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>
......@@ -462,7 +475,7 @@ struct CopyConstructArray_;
template <typename T>
struct CopyConstructArray_<T, T*, true> {
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);
}
};
......@@ -470,7 +483,7 @@ struct CopyConstructArray_<T, T*, true> {
template <typename T>
struct CopyConstructArray_<T, const T*, true> {
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);
}
};
......@@ -554,6 +567,11 @@ heapArray(Iterator begin, Iterator end) {
return builder.finish();
}
template <typename T>
inline Array<T> heapArray(std::initializer_list<T> init) {
return heapArray<T>(init.begin(), init.end());
}
} // namespace kj
#endif // KJ_ARRAY_H_
......@@ -176,6 +176,10 @@ template <typename T> struct RemoveReference_ { typedef T Type; };
template <typename T> struct RemoveReference_<T&> { typedef 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 T> struct IsLvalueReference_<T&> { static constexpr bool value = true; };
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:
Own(const Own& other) = delete;
inline Own(Own&& other) noexcept
: 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>
inline Own(Own<U>&& other) noexcept
: disposer(other.disposer), ptr(other.ptr) {
......@@ -126,9 +129,12 @@ private:
T* ptrCopy = ptr;
if (ptrCopy != nullptr) {
ptr = nullptr;
disposer->dispose(ptrCopy);
disposer->dispose(const_cast<RemoveConst<T>*>(ptrCopy));
}
}
template <typename U>
friend class Own;
};
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