Add allocator, start work on box
This commit is contained in:
@ -1,8 +1,10 @@
|
|||||||
cc_library(
|
cc_library(
|
||||||
name = "asl",
|
name = "asl",
|
||||||
hdrs = [
|
hdrs = [
|
||||||
|
"allocator.hpp",
|
||||||
"annotations.hpp",
|
"annotations.hpp",
|
||||||
"assert.hpp",
|
"assert.hpp",
|
||||||
|
"box.hpp",
|
||||||
"config.hpp",
|
"config.hpp",
|
||||||
"format.hpp",
|
"format.hpp",
|
||||||
"functional.hpp",
|
"functional.hpp",
|
||||||
@ -19,6 +21,7 @@ cc_library(
|
|||||||
"utility.hpp",
|
"utility.hpp",
|
||||||
],
|
],
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"allocator.cpp",
|
||||||
"format.cpp",
|
"format.cpp",
|
||||||
"print.cpp",
|
"print.cpp",
|
||||||
],
|
],
|
||||||
@ -36,6 +39,7 @@ cc_library(
|
|||||||
"//asl/testing",
|
"//asl/testing",
|
||||||
],
|
],
|
||||||
) for name in [
|
) for name in [
|
||||||
|
"box",
|
||||||
"format",
|
"format",
|
||||||
"functional",
|
"functional",
|
||||||
"integers",
|
"integers",
|
||||||
|
38
asl/allocator.cpp
Normal file
38
asl/allocator.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "asl/allocator.hpp"
|
||||||
|
#include "asl/assert.hpp"
|
||||||
|
#include "asl/utility.hpp"
|
||||||
|
#include "asl/memory.hpp"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
// @Todo zalloc
|
||||||
|
// @Todo Cookies
|
||||||
|
// @Todo Debug values
|
||||||
|
|
||||||
|
void* asl::GlobalHeap::alloc(const layout& layout)
|
||||||
|
{
|
||||||
|
void* ptr = ::_aligned_malloc(
|
||||||
|
static_cast<size_t>(layout.size),
|
||||||
|
static_cast<size_t>(layout.align));
|
||||||
|
ASL_ASSERT(ptr != nullptr); // @Todo panic
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* asl::GlobalHeap::realloc(void* old_ptr, const layout& old_layout, const layout& new_layout)
|
||||||
|
{
|
||||||
|
if (new_layout.align <= old_layout.align)
|
||||||
|
{
|
||||||
|
void* new_ptr = ::realloc(old_ptr, static_cast<size_t>(new_layout.size));
|
||||||
|
ASL_ASSERT(new_ptr != nullptr); // @Todo panic
|
||||||
|
return new_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* new_ptr = alloc(new_layout);
|
||||||
|
asl::memcpy(new_ptr, old_ptr, asl::min(old_layout.size, new_layout.size));
|
||||||
|
return new_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void asl::GlobalHeap::dealloc(void* ptr, const layout&)
|
||||||
|
{
|
||||||
|
::free(ptr);
|
||||||
|
}
|
28
asl/allocator.hpp
Normal file
28
asl/allocator.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "asl/layout.hpp"
|
||||||
|
#include "asl/meta.hpp"
|
||||||
|
|
||||||
|
namespace asl
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept allocator = requires(T& alloc, layout layout, void* ptr)
|
||||||
|
{
|
||||||
|
{ alloc.alloc(layout) } -> same_as<void*>;
|
||||||
|
{ alloc.realloc(ptr, layout, layout) } -> same_as<void*>;
|
||||||
|
alloc.dealloc(ptr, layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
class GlobalHeap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void* alloc(const layout&);
|
||||||
|
static void* realloc(void* ptr, const layout& old, const layout& new_layout);
|
||||||
|
static void dealloc(void* ptr, const layout&);
|
||||||
|
};
|
||||||
|
static_assert(allocator<GlobalHeap>);
|
||||||
|
|
||||||
|
using DefaultAllocator = GlobalHeap;
|
||||||
|
|
||||||
|
} // namespace asl
|
19
asl/box.hpp
Normal file
19
asl/box.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "asl/allocator.hpp"
|
||||||
|
#include "asl/annotations.hpp"
|
||||||
|
|
||||||
|
namespace asl
|
||||||
|
{
|
||||||
|
|
||||||
|
template<is_object T, allocator Allocator = DefaultAllocator>
|
||||||
|
class box
|
||||||
|
{
|
||||||
|
T* m_ptr;
|
||||||
|
ASL_NO_UNIQUE_ADDRESS Allocator m_alloc;
|
||||||
|
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asl
|
||||||
|
|
@ -4,11 +4,11 @@
|
|||||||
#include "asl/memory.hpp"
|
#include "asl/memory.hpp"
|
||||||
|
|
||||||
void asl::format_internals::format(
|
void asl::format_internals::format(
|
||||||
writer* writer,
|
Writer* writer,
|
||||||
string_view fmt,
|
string_view fmt,
|
||||||
span<const type_erased_arg> args)
|
span<const type_erased_arg> args)
|
||||||
{
|
{
|
||||||
formatter f(writer);
|
Formatter f(writer);
|
||||||
|
|
||||||
const auto* arg_it = args.begin();
|
const auto* arg_it = args.begin();
|
||||||
const auto* arg_end = args.end();
|
const auto* arg_end = args.end();
|
||||||
@ -74,22 +74,22 @@ void asl::format_internals::format(
|
|||||||
f.write(fmt);
|
f.write(fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, const char* str)
|
void asl::AslFormat(Formatter& f, const char* str)
|
||||||
{
|
{
|
||||||
f.write({str, asl::strlen(str)});
|
f.write({str, asl::strlen(str)});
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, float)
|
void asl::AslFormat(Formatter& f, float)
|
||||||
{
|
{
|
||||||
f.write("<FLOAT>"); // @Todo Float formatting
|
f.write("<FLOAT>"); // @Todo Float formatting
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, double)
|
void asl::AslFormat(Formatter& f, double)
|
||||||
{
|
{
|
||||||
f.write("<DOUBLE>"); // @Todo Float formatting
|
f.write("<DOUBLE>"); // @Todo Float formatting
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, bool v)
|
void asl::AslFormat(Formatter& f, bool v)
|
||||||
{
|
{
|
||||||
if (v)
|
if (v)
|
||||||
{
|
{
|
||||||
@ -101,22 +101,22 @@ void asl::AslFormat(formatter& f, bool v)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, uint8_t v)
|
void asl::AslFormat(Formatter& f, uint8_t v)
|
||||||
{
|
{
|
||||||
AslFormat(f, static_cast<uint64_t>(v));
|
AslFormat(f, static_cast<uint64_t>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, uint16_t v)
|
void asl::AslFormat(Formatter& f, uint16_t v)
|
||||||
{
|
{
|
||||||
AslFormat(f, static_cast<uint64_t>(v));
|
AslFormat(f, static_cast<uint64_t>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, uint32_t v)
|
void asl::AslFormat(Formatter& f, uint32_t v)
|
||||||
{
|
{
|
||||||
AslFormat(f, static_cast<uint64_t>(v));
|
AslFormat(f, static_cast<uint64_t>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, uint64_t v)
|
void asl::AslFormat(Formatter& f, uint64_t v)
|
||||||
{
|
{
|
||||||
static constexpr char s_pairs_storage[] = {
|
static constexpr char s_pairs_storage[] = {
|
||||||
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4',
|
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4',
|
||||||
@ -180,22 +180,22 @@ void asl::AslFormat(formatter& f, uint64_t v)
|
|||||||
f.write(string_view(buffer, kMaxDigits).substr(cursor));
|
f.write(string_view(buffer, kMaxDigits).substr(cursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, int8_t v)
|
void asl::AslFormat(Formatter& f, int8_t v)
|
||||||
{
|
{
|
||||||
AslFormat(f, static_cast<int64_t>(v));
|
AslFormat(f, static_cast<int64_t>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, int16_t v)
|
void asl::AslFormat(Formatter& f, int16_t v)
|
||||||
{
|
{
|
||||||
AslFormat(f, static_cast<int64_t>(v));
|
AslFormat(f, static_cast<int64_t>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, int32_t v)
|
void asl::AslFormat(Formatter& f, int32_t v)
|
||||||
{
|
{
|
||||||
AslFormat(f, static_cast<int64_t>(v));
|
AslFormat(f, static_cast<int64_t>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(formatter& f, int64_t v)
|
void asl::AslFormat(Formatter& f, int64_t v)
|
||||||
{
|
{
|
||||||
if (v < 0)
|
if (v < 0)
|
||||||
{
|
{
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
class formatter;
|
class Formatter;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept formattable = requires (formatter& f, const T& value)
|
concept formattable = requires (Formatter& f, const T& value)
|
||||||
{
|
{
|
||||||
AslFormat(f, value);
|
AslFormat(f, value);
|
||||||
};
|
};
|
||||||
@ -23,10 +23,10 @@ namespace format_internals
|
|||||||
struct type_erased_arg
|
struct type_erased_arg
|
||||||
{
|
{
|
||||||
const void* data;
|
const void* data;
|
||||||
void (*fn)(formatter&, const void*);
|
void (*fn)(Formatter&, const void*);
|
||||||
|
|
||||||
template<formattable T>
|
template<formattable T>
|
||||||
static constexpr void erased_fn(formatter& f, const void* data)
|
static constexpr void erased_fn(Formatter& f, const void* data)
|
||||||
{
|
{
|
||||||
AslFormat(f, *reinterpret_cast<const T*>(data));
|
AslFormat(f, *reinterpret_cast<const T*>(data));
|
||||||
}
|
}
|
||||||
@ -38,16 +38,16 @@ struct type_erased_arg
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
void format(writer*, string_view fmt, span<const type_erased_arg> args);
|
void format(Writer*, string_view fmt, span<const type_erased_arg> args);
|
||||||
|
|
||||||
} // namespace internals
|
} // namespace internals
|
||||||
|
|
||||||
class formatter
|
class Formatter
|
||||||
{
|
{
|
||||||
writer* m_writer;
|
Writer* m_writer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit constexpr formatter(writer* writer)
|
explicit constexpr Formatter(Writer* writer)
|
||||||
: m_writer{writer}
|
: m_writer{writer}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<formattable... Args>
|
template<formattable... Args>
|
||||||
void format(writer* w, string_view fmt, const Args&... args)
|
void format(Writer* w, string_view fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
if constexpr (types_count<Args...> > 0)
|
if constexpr (types_count<Args...> > 0)
|
||||||
{
|
{
|
||||||
@ -75,26 +75,26 @@ void format(writer* w, string_view fmt, const Args&... args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<isize_t N>
|
template<isize_t N>
|
||||||
void AslFormat(formatter& f, const char (&str)[N])
|
void AslFormat(Formatter& f, const char (&str)[N])
|
||||||
{
|
{
|
||||||
f.write(str, N - 1);
|
f.write(str, N - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AslFormat(formatter& f, const char* str);
|
void AslFormat(Formatter& f, const char* str);
|
||||||
|
|
||||||
void AslFormat(formatter& f, float);
|
void AslFormat(Formatter& f, float);
|
||||||
void AslFormat(formatter& f, double);
|
void AslFormat(Formatter& f, double);
|
||||||
|
|
||||||
void AslFormat(formatter& f, bool);
|
void AslFormat(Formatter& f, bool);
|
||||||
|
|
||||||
void AslFormat(formatter& f, uint8_t);
|
void AslFormat(Formatter& f, uint8_t);
|
||||||
void AslFormat(formatter& f, uint16_t);
|
void AslFormat(Formatter& f, uint16_t);
|
||||||
void AslFormat(formatter& f, uint32_t);
|
void AslFormat(Formatter& f, uint32_t);
|
||||||
void AslFormat(formatter& f, uint64_t);
|
void AslFormat(Formatter& f, uint64_t);
|
||||||
|
|
||||||
void AslFormat(formatter& f, int8_t);
|
void AslFormat(Formatter& f, int8_t);
|
||||||
void AslFormat(formatter& f, int16_t);
|
void AslFormat(Formatter& f, int16_t);
|
||||||
void AslFormat(formatter& f, int32_t);
|
void AslFormat(Formatter& f, int32_t);
|
||||||
void AslFormat(formatter& f, int64_t);
|
void AslFormat(Formatter& f, int64_t);
|
||||||
|
|
||||||
} // namespace asl
|
} // namespace asl
|
||||||
|
@ -7,12 +7,12 @@
|
|||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
class writer
|
class Writer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
writer() = default;
|
Writer() = default;
|
||||||
ASL_DELETE_COPY_MOVE(writer);
|
ASL_DELETE_COPY_MOVE(Writer);
|
||||||
virtual ~writer() = default;
|
virtual ~Writer() = default;
|
||||||
|
|
||||||
virtual void write(span<const byte>) = 0;
|
virtual void write(span<const byte>) = 0;
|
||||||
};
|
};
|
||||||
|
@ -24,6 +24,12 @@ struct layout
|
|||||||
{
|
{
|
||||||
return layout{ size_of<T>, align_of<T> };
|
return layout{ size_of<T>, align_of<T> };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<is_object T>
|
||||||
|
static constexpr layout array(isize_t size)
|
||||||
|
{
|
||||||
|
return layout{ size_of<T> * size, align_of<T> };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace asl
|
} // namespace asl
|
||||||
|
@ -15,6 +15,11 @@ constexpr isize_t memcmp(const void* a, const void* b, isize_t size)
|
|||||||
return __builtin_memcmp(a, b, static_cast<size_t>(size));
|
return __builtin_memcmp(a, b, static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr void memcpy(void* dst, const void* src, isize_t size)
|
||||||
|
{
|
||||||
|
__builtin_memcpy(dst, src, static_cast<size_t>(size));
|
||||||
|
}
|
||||||
|
|
||||||
constexpr isize_t strlen(const char* s)
|
constexpr isize_t strlen(const char* s)
|
||||||
{
|
{
|
||||||
return static_cast<isize_t>(__builtin_strlen(s));
|
return static_cast<isize_t>(__builtin_strlen(s));
|
||||||
|
@ -21,10 +21,10 @@ template<typename U, typename V> struct _select_helper<true, U, V>
|
|||||||
|
|
||||||
template<bool kSelect, typename U, typename V> using select_t = _select_helper<kSelect, U, V>::type;
|
template<bool kSelect, typename U, typename V> using select_t = _select_helper<kSelect, U, V>::type;
|
||||||
|
|
||||||
template<typename U, typename V> struct _is_same_helper : false_type {};
|
template<typename U, typename V> struct _same_as_helper : false_type {};
|
||||||
template<typename T> struct _is_same_helper<T, T> : true_type {};
|
template<typename T> struct _same_as_helper<T, T> : true_type {};
|
||||||
|
|
||||||
template<typename U, typename V> concept same_as = _is_same_helper<U, V>::value && _is_same_helper<V, U>::value;
|
template<typename U, typename V> concept same_as = _same_as_helper<U, V>::value && _same_as_helper<V, U>::value;
|
||||||
|
|
||||||
template<typename T> auto _as_lref_helper(int) -> id<T&>;
|
template<typename T> auto _as_lref_helper(int) -> id<T&>;
|
||||||
template<typename T> auto _as_lref_helper(...) -> id<T>;
|
template<typename T> auto _as_lref_helper(...) -> id<T>;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
// @Todo Optimize this, maybe make buffered
|
// @Todo Optimize this, maybe make buffered
|
||||||
class ConsoleWriter : public asl::writer
|
class ConsoleWriter : public asl::Writer
|
||||||
{
|
{
|
||||||
FILE* m_handle;
|
FILE* m_handle;
|
||||||
|
|
||||||
@ -18,13 +18,13 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
asl::writer* asl::print_internals::get_stdout_writer()
|
asl::Writer* asl::print_internals::get_stdout_writer()
|
||||||
{
|
{
|
||||||
static ConsoleWriter s_writer{stdout};
|
static ConsoleWriter s_writer{stdout};
|
||||||
return &s_writer;
|
return &s_writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
asl::writer* asl::print_internals::get_stderr_writer()
|
asl::Writer* asl::print_internals::get_stderr_writer()
|
||||||
{
|
{
|
||||||
static ConsoleWriter s_writer{stderr};
|
static ConsoleWriter s_writer{stderr};
|
||||||
return &s_writer;
|
return &s_writer;
|
||||||
|
@ -9,8 +9,8 @@ namespace print_internals
|
|||||||
{
|
{
|
||||||
|
|
||||||
// @Todo Make print writers thread safe
|
// @Todo Make print writers thread safe
|
||||||
writer* get_stdout_writer();
|
Writer* get_stdout_writer();
|
||||||
writer* get_stderr_writer();
|
Writer* get_stderr_writer();
|
||||||
|
|
||||||
} // namespace print_internals
|
} // namespace print_internals
|
||||||
|
|
||||||
|
6
asl/tests/box_tests.cpp
Normal file
6
asl/tests/box_tests.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "asl/box.hpp"
|
||||||
|
|
||||||
|
#include "asl/testing/testing.hpp"
|
||||||
|
|
||||||
|
static_assert(sizeof(asl::box<int>) == sizeof(int*));
|
||||||
|
|
@ -1,26 +1,25 @@
|
|||||||
#include "asl/format.hpp"
|
#include "asl/format.hpp"
|
||||||
#include "asl/testing/testing.hpp"
|
#include "asl/testing/testing.hpp"
|
||||||
#include "asl/print.hpp"
|
#include "asl/allocator.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
// @Todo Improve this to use our utilities, not the C stdlib
|
|
||||||
|
|
||||||
static_assert(asl::formattable<decltype("Hello")>);
|
static_assert(asl::formattable<decltype("Hello")>);
|
||||||
|
|
||||||
class StringSink : public asl::writer
|
class StringSink : public asl::Writer
|
||||||
{
|
{
|
||||||
|
// @Todo Use string, once we have it, or a buffer
|
||||||
isize_t m_current_len{};
|
isize_t m_current_len{};
|
||||||
char* m_data{};
|
char* m_data{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void write(asl::span<const asl::byte> str) override
|
void write(asl::span<const asl::byte> str) override
|
||||||
{
|
{
|
||||||
m_data = (char*)realloc(m_data, (size_t)(m_current_len + str.size()));
|
m_data = reinterpret_cast<char*>(asl::GlobalHeap::realloc(
|
||||||
memcpy(m_data + m_current_len, str.data(), (size_t)str.size());
|
m_data,
|
||||||
|
asl::layout::array<char>(m_current_len),
|
||||||
|
asl::layout::array<char>(m_current_len + str.size())));
|
||||||
|
|
||||||
|
asl::memcpy(m_data + m_current_len, str.data(), str.size());
|
||||||
|
|
||||||
m_current_len += str.size();
|
m_current_len += str.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +28,7 @@ public:
|
|||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
m_current_len = 0;
|
m_current_len = 0;
|
||||||
free(m_data);
|
asl::GlobalHeap::dealloc(m_data, asl::layout::array<char>(m_current_len));
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -35,6 +35,7 @@ static_assert(!asl::trivially_copy_constructible<NonCopyConstructible>);
|
|||||||
static_assert(asl::move_constructible<int>);
|
static_assert(asl::move_constructible<int>);
|
||||||
static_assert(asl::move_constructible<TriviallyMoveConstructible>);
|
static_assert(asl::move_constructible<TriviallyMoveConstructible>);
|
||||||
static_assert(asl::move_constructible<MoveConstructible>);
|
static_assert(asl::move_constructible<MoveConstructible>);
|
||||||
|
static_assert(asl::move_constructible<CopyConstructible>);
|
||||||
static_assert(!asl::move_constructible<NonMoveConstructible>);
|
static_assert(!asl::move_constructible<NonMoveConstructible>);
|
||||||
|
|
||||||
static_assert(asl::trivially_move_constructible<int>);
|
static_assert(asl::trivially_move_constructible<int>);
|
||||||
|
@ -24,6 +24,12 @@ constexpr U bit_cast(T value) requires (size_of<T> == size_of<U>)
|
|||||||
return __builtin_bit_cast(U, value);
|
return __builtin_bit_cast(U, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T min(T a, T b)
|
||||||
|
{
|
||||||
|
return (a <= b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
#define ASL_DELETE_COPY(T) \
|
#define ASL_DELETE_COPY(T) \
|
||||||
T(const T&) = delete; \
|
T(const T&) = delete; \
|
||||||
T& operator=(const T&) = delete;
|
T& operator=(const T&) = delete;
|
||||||
|
Reference in New Issue
Block a user