[proxy](2/n) provide proxy layers for type traits (#717)
* [proxy](2/n) provide proxy layers for type traits * fix after rebasing
This commit is contained in:
committed by
GitHub
parent
7db1f243cc
commit
2cc74eac10
18
.github/workflows/main.yml
vendored
18
.github/workflows/main.yml
vendored
@@ -495,21 +495,23 @@ jobs:
|
||||
run: ${{github.workspace}}/build/fuzzing/snmalloc-fuzzer
|
||||
|
||||
self-vendored:
|
||||
name: Self Vendored STL Functionality
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-2022
|
||||
cxx: clang-cl
|
||||
cc: clang-cl
|
||||
- os: ubuntu-latest
|
||||
cxx: clang++
|
||||
cc: clang
|
||||
- os: ubuntu-latest
|
||||
cxx: g++
|
||||
cc: gcc
|
||||
- os: ubuntu-24.04
|
||||
cxx: clang++-18
|
||||
cc: clang-18
|
||||
- os: ubuntu-24.04
|
||||
cxx: g++-14
|
||||
cc: gcc-14
|
||||
- os: macos-latest
|
||||
cxx: clang++
|
||||
cc: clang
|
||||
cc: clang
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -524,7 +526,7 @@ jobs:
|
||||
- name: Prepare Ubuntu
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt install ninja-build
|
||||
sudo apt-get install -y ninja-build
|
||||
- name: Configure CMake
|
||||
run: >
|
||||
cmake
|
||||
|
||||
@@ -69,10 +69,10 @@ namespace snmalloc
|
||||
* must explicitly give their address_t.
|
||||
*
|
||||
* This somewhat obtuse way of spelling the defaulting is necessary so
|
||||
* that all arguments to std::conditional_t are valid, even if they
|
||||
* that all arguments to stl::conditional_t are valid, even if they
|
||||
* wouldn't be valid in context. One might rather wish to say
|
||||
*
|
||||
* std::conditional_t<..., uintptr_t, Arch::address_t>
|
||||
* stl::conditional_t<..., uintptr_t, Arch::address_t>
|
||||
*
|
||||
* but that requires that Arch::address_t always be given, precisely
|
||||
* the thing we're trying to avoid with the conditional.
|
||||
@@ -83,7 +83,7 @@ namespace snmalloc
|
||||
using address_t = uintptr_t;
|
||||
};
|
||||
|
||||
using address_t = typename std::conditional_t<
|
||||
using address_t = typename stl::conditional_t<
|
||||
(Arch::aal_features & IntegerPointers) != 0,
|
||||
default_address_t,
|
||||
Arch>::address_t;
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
# include "../ds_core/ds_core.h"
|
||||
# include "aal_consts.h"
|
||||
|
||||
# include <cstdint>
|
||||
# include <utility>
|
||||
# include <stdint.h>
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
@@ -16,10 +15,10 @@ namespace snmalloc
|
||||
template<typename AAL>
|
||||
concept IsAAL_static_members =
|
||||
requires() {
|
||||
typename std::integral_constant<uint64_t, AAL::aal_features>;
|
||||
typename std::integral_constant<int, AAL::aal_name>;
|
||||
typename std::integral_constant<std::size_t, AAL::bits>;
|
||||
typename std::integral_constant<std::size_t, AAL::address_bits>;
|
||||
typename stl::integral_constant<uint64_t, AAL::aal_features>;
|
||||
typename stl::integral_constant<int, AAL::aal_name>;
|
||||
typename stl::integral_constant<size_t, AAL::bits>;
|
||||
typename stl::integral_constant<size_t, AAL::address_bits>;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -118,7 +118,8 @@ namespace snmalloc
|
||||
static_assert(B::wildness == capptr::dimension::Wildness::Wild);
|
||||
|
||||
static const size_t sz = sizeof(
|
||||
std::conditional<std::is_same_v<std::remove_cv<T>, void>, void*, T>);
|
||||
stl::
|
||||
conditional_t<stl::is_same_v<stl::remove_cv_t<T>, void>, void*, T>);
|
||||
|
||||
UNUSED(ls);
|
||||
auto address = address_cast(p);
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace snmalloc
|
||||
/**
|
||||
* Use one of the default range configurations
|
||||
*/
|
||||
using LocalState = std::conditional_t<
|
||||
using LocalState = stl::conditional_t<
|
||||
mitigations(metadata_protection),
|
||||
MetaProtectedRangeLocalState<Pal, Pagemap, Base>,
|
||||
StandardLocalState<Pal, Pagemap, Base>>;
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace snmalloc
|
||||
CommitRange<PAL>,
|
||||
// In case of huge pages, we don't want to give each thread its own huge
|
||||
// page, so commit in the global range.
|
||||
std::conditional_t<
|
||||
stl::conditional_t<
|
||||
(max_page_chunk_size_bits > MIN_CHUNK_BITS),
|
||||
LargeBuddyRange<
|
||||
max_page_chunk_size_bits,
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace snmalloc
|
||||
struct BasicAuthmap
|
||||
{
|
||||
static_assert(
|
||||
std::is_same_v<capptr::Arena<void>, typename ConcreteMap::EntryType>,
|
||||
stl::is_same_v<capptr::Arena<void>, typename ConcreteMap::EntryType>,
|
||||
"BasicAuthmap's ConcreteMap must have capptr::Arena<void> element type!");
|
||||
|
||||
private:
|
||||
@@ -70,7 +70,7 @@ namespace snmalloc
|
||||
* Pick between the two above implementations based on StrictProvenance
|
||||
*/
|
||||
template<typename CA>
|
||||
using DefaultAuthmap = std::conditional_t<
|
||||
using DefaultAuthmap = stl::conditional_t<
|
||||
aal_supports<StrictProvenance>,
|
||||
BasicAuthmap<CA>,
|
||||
DummyAuthmap>;
|
||||
|
||||
@@ -228,7 +228,7 @@ namespace snmalloc
|
||||
* covers the whole range. Uses template insanity to make this work.
|
||||
*/
|
||||
template<bool exists = MAX_SIZE_BITS != (bits::BITS - 1)>
|
||||
std::enable_if_t<exists>
|
||||
stl::enable_if_t<exists>
|
||||
parent_dealloc_range(capptr::Arena<void> base, size_t size)
|
||||
{
|
||||
static_assert(
|
||||
@@ -343,7 +343,7 @@ namespace snmalloc
|
||||
/* The large buddy allocator always deals in Arena-bounded pointers. */
|
||||
using ChunkBounds = capptr::bounds::Arena;
|
||||
static_assert(
|
||||
std::is_same_v<typename ParentRange::ChunkBounds, ChunkBounds>);
|
||||
stl::is_same_v<typename ParentRange::ChunkBounds, ChunkBounds>);
|
||||
|
||||
constexpr Type() = default;
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ namespace snmalloc
|
||||
using Entry = PagemapEntry;
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<PagemapEntry, typename ConcreteMap::EntryType>,
|
||||
stl::is_same_v<PagemapEntry, typename ConcreteMap::EntryType>,
|
||||
"BasicPagemap's PagemapEntry and ConcreteMap disagree!");
|
||||
|
||||
static_assert(
|
||||
std::is_base_of_v<MetaEntryBase, PagemapEntry>,
|
||||
stl::is_base_of_v<MetaEntryBase, PagemapEntry>,
|
||||
"BasicPagemap's PagemapEntry type is not a MetaEntryBase");
|
||||
|
||||
/**
|
||||
@@ -115,7 +115,7 @@ namespace snmalloc
|
||||
*/
|
||||
template<bool fixed_range_ = fixed_range>
|
||||
static SNMALLOC_FAST_PATH
|
||||
std::enable_if_t<fixed_range_, std::pair<address_t, address_t>>
|
||||
stl::enable_if_t<fixed_range_, std::pair<address_t, address_t>>
|
||||
get_bounds()
|
||||
{
|
||||
static_assert(fixed_range_ == fixed_range, "Don't set SFINAE parameter!");
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace snmalloc
|
||||
template<typename Anc>
|
||||
Anc* ancestor()
|
||||
{
|
||||
if constexpr (std::is_same_v<Anc, Parent>)
|
||||
if constexpr (stl::is_same_v<Anc, Parent>)
|
||||
{
|
||||
return &parent;
|
||||
}
|
||||
@@ -119,7 +119,7 @@ namespace snmalloc
|
||||
template<typename Anc>
|
||||
Anc* ancestor()
|
||||
{
|
||||
if constexpr (std::is_same_v<Anc, Parent>)
|
||||
if constexpr (stl::is_same_v<Anc, Parent>)
|
||||
{
|
||||
return &parent;
|
||||
}
|
||||
@@ -150,7 +150,7 @@ namespace snmalloc
|
||||
template<typename Anc>
|
||||
Anc* ancestor()
|
||||
{
|
||||
if constexpr (std::is_same_v<Anc, Parent>)
|
||||
if constexpr (stl::is_same_v<Anc, Parent>)
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace snmalloc
|
||||
using ChunkBounds = typename ActualParentRange::ChunkBounds;
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<ChunkBounds, typename ParentRange::ChunkBounds>,
|
||||
stl::is_same_v<ChunkBounds, typename ParentRange::ChunkBounds>,
|
||||
"Grandparent and optional parent range chunk bounds must be equal");
|
||||
|
||||
constexpr Type() = default;
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
namespace snmalloc
|
||||
{
|
||||
template<typename PAL>
|
||||
std::enable_if_t<pal_supports<Entropy, PAL>, uint64_t> get_entropy64()
|
||||
stl::enable_if_t<pal_supports<Entropy, PAL>, uint64_t> get_entropy64()
|
||||
{
|
||||
return PAL::get_entropy64();
|
||||
}
|
||||
|
||||
template<typename PAL>
|
||||
std::enable_if_t<!pal_supports<Entropy, PAL>, uint64_t> get_entropy64()
|
||||
stl::enable_if_t<!pal_supports<Entropy, PAL>, uint64_t> get_entropy64()
|
||||
{
|
||||
#ifdef SNMALLOC_PLATFORM_HAS_GETENTROPY
|
||||
return DefaultPal::get_entropy64();
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace snmalloc
|
||||
void push(T* item)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<decltype(T::next), stl::Atomic<T*>>::value,
|
||||
stl::is_same_v<decltype(T::next), stl::Atomic<T*>>,
|
||||
"T->next must be an stl::Atomic<T*>");
|
||||
|
||||
return push(item, item);
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace snmalloc
|
||||
* fixed-range pagemaps, whose size depends on dynamic configuration.
|
||||
*/
|
||||
template<bool has_bounds_ = has_bounds>
|
||||
static constexpr std::enable_if_t<!has_bounds_, size_t> required_size()
|
||||
static constexpr stl::enable_if_t<!has_bounds_, size_t> required_size()
|
||||
{
|
||||
static_assert(
|
||||
has_bounds_ == has_bounds, "Don't set SFINAE template parameter!");
|
||||
@@ -99,7 +99,7 @@ namespace snmalloc
|
||||
* `required_size` is enabled for the has-bounds case.
|
||||
*/
|
||||
template<bool has_bounds_ = has_bounds>
|
||||
std::enable_if_t<!has_bounds_> init(T* address)
|
||||
stl::enable_if_t<!has_bounds_> init(T* address)
|
||||
{
|
||||
SNMALLOC_ASSERT(!is_initialised());
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace snmalloc
|
||||
* Returns usable range after pagemap has been allocated
|
||||
*/
|
||||
template<bool has_bounds_ = has_bounds>
|
||||
std::enable_if_t<has_bounds_, std::pair<void*, size_t>>
|
||||
stl::enable_if_t<has_bounds_, std::pair<void*, size_t>>
|
||||
init(void* b, size_t s)
|
||||
{
|
||||
SNMALLOC_ASSERT(!is_initialised());
|
||||
@@ -174,7 +174,7 @@ namespace snmalloc
|
||||
* Initialise the pagemap without bounds.
|
||||
*/
|
||||
template<bool randomize_position, bool has_bounds_ = has_bounds>
|
||||
std::enable_if_t<!has_bounds_> init()
|
||||
stl::enable_if_t<!has_bounds_> init()
|
||||
{
|
||||
SNMALLOC_ASSERT(!is_initialised());
|
||||
|
||||
@@ -250,7 +250,7 @@ namespace snmalloc
|
||||
}
|
||||
|
||||
template<bool has_bounds_ = has_bounds>
|
||||
std::enable_if_t<has_bounds_, std::pair<address_t, size_t>> get_bounds()
|
||||
stl::enable_if_t<has_bounds_, std::pair<address_t, size_t>> get_bounds()
|
||||
{
|
||||
SNMALLOC_ASSERT(is_initialised());
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
#include "../ds_core/ds_core.h"
|
||||
#include "flaglock.h"
|
||||
#include "snmalloc/stl/atomic.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include "snmalloc/stl/type_traits.h"
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
#include "defines.h"
|
||||
#include "snmalloc/stl/atomic.h"
|
||||
#include "snmalloc/stl/type_traits.h"
|
||||
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#if defined(_MSC_VER)
|
||||
# include <intsafe.h>
|
||||
#endif
|
||||
@@ -55,7 +55,7 @@ namespace snmalloc
|
||||
template<typename T = size_t, typename S>
|
||||
constexpr T one_at_bit(S shift)
|
||||
{
|
||||
static_assert(std::is_integral_v<T>, "Type must be integral");
|
||||
static_assert(stl::is_integral_v<T>, "Type must be integral");
|
||||
SNMALLOC_ASSERT(sizeof(T) * 8 > static_cast<size_t>(shift));
|
||||
return (static_cast<T>(1)) << shift;
|
||||
}
|
||||
@@ -95,15 +95,15 @@ namespace snmalloc
|
||||
return BITS - index - 1;
|
||||
# endif
|
||||
#else
|
||||
if constexpr (std::is_same_v<unsigned long, std::size_t>)
|
||||
if constexpr (stl::is_same_v<unsigned long, std::size_t>)
|
||||
{
|
||||
return static_cast<size_t>(__builtin_clzl(x));
|
||||
}
|
||||
else if constexpr (std::is_same_v<unsigned long long, std::size_t>)
|
||||
else if constexpr (stl::is_same_v<unsigned long long, std::size_t>)
|
||||
{
|
||||
return static_cast<size_t>(__builtin_clzll(x));
|
||||
}
|
||||
else if constexpr (std::is_same_v<unsigned int, std::size_t>)
|
||||
else if constexpr (stl::is_same_v<unsigned int, std::size_t>)
|
||||
{
|
||||
return static_cast<size_t>(__builtin_clz(x));
|
||||
}
|
||||
@@ -182,15 +182,15 @@ namespace snmalloc
|
||||
return _tzcnt_u32(static_cast<unsigned int>(x));
|
||||
# endif
|
||||
#else
|
||||
if constexpr (std::is_same_v<unsigned long, std::size_t>)
|
||||
if constexpr (stl::is_same_v<unsigned long, std::size_t>)
|
||||
{
|
||||
return static_cast<size_t>(__builtin_ctzl(x));
|
||||
}
|
||||
else if constexpr (std::is_same_v<unsigned long long, std::size_t>)
|
||||
else if constexpr (stl::is_same_v<unsigned long long, std::size_t>)
|
||||
{
|
||||
return static_cast<size_t>(__builtin_ctzll(x));
|
||||
}
|
||||
else if constexpr (std::is_same_v<unsigned int, std::size_t>)
|
||||
else if constexpr (stl::is_same_v<unsigned int, std::size_t>)
|
||||
{
|
||||
return static_cast<size_t>(__builtin_ctz(x));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include "snmalloc/stl/type_traits.h"
|
||||
|
||||
/**
|
||||
* C++20 concepts are referenced as if they were types in declarations within
|
||||
@@ -20,31 +20,15 @@
|
||||
#ifdef __cpp_concepts
|
||||
namespace snmalloc
|
||||
{
|
||||
/**
|
||||
* C++20 concepts are more than just new syntax; there's a new support
|
||||
* library specified as well. As C++20 is quite new, however, there are some
|
||||
* environments, notably Clang, that understand the syntax but do not yet
|
||||
* offer the library. Fortunately, alternate pronouciations are possible.
|
||||
*/
|
||||
# ifdef _cpp_lib_concepts
|
||||
/**
|
||||
* ConceptSame<T,U> is true if T and U are the same type and false otherwise.
|
||||
* When specifying a concept, use ConceptSame<U> to indicate that an
|
||||
* expression must evaluate precisely to the type U.
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
concept ConceptSame = std::same_as<T, U>;
|
||||
# else
|
||||
template<typename T, typename U>
|
||||
concept ConceptSame = std::is_same<T, U>::value;
|
||||
# endif
|
||||
concept ConceptSame = stl::is_same_v<T, U>;
|
||||
|
||||
/**
|
||||
* Equivalence mod std::remove_reference
|
||||
* Equivalence mod stl::remove_reference
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
concept ConceptSameModRef =
|
||||
ConceptSame<std::remove_reference_t<T>, std::remove_reference_t<U>>;
|
||||
ConceptSame<stl::remove_reference_t<T>, stl::remove_reference_t<U>>;
|
||||
|
||||
/**
|
||||
* Some of the types in snmalloc are circular in their definition and use
|
||||
@@ -73,7 +57,7 @@ namespace snmalloc
|
||||
constexpr bool is_type_complete_v = false;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_type_complete_v<T, std::void_t<decltype(sizeof(T))>> = true;
|
||||
constexpr bool is_type_complete_v<T, stl::void_t<decltype(sizeof(T))>> = true;
|
||||
|
||||
} // namespace snmalloc
|
||||
#endif
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#include "bits.h"
|
||||
#include "snmalloc/ds_core/defines.h"
|
||||
#include "snmalloc/stl/type_traits.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
@@ -104,7 +104,7 @@ namespace snmalloc
|
||||
template<
|
||||
typename Fn,
|
||||
typename =
|
||||
std::enable_if_t<!std::is_same_v<std::decay_t<Fn>, function_ref>>>
|
||||
stl::enable_if_t<!stl::is_same_v<std::decay_t<Fn>, function_ref>>>
|
||||
function_ref(Fn&& fn)
|
||||
{
|
||||
data_ = static_cast<void*>(&fn);
|
||||
@@ -123,7 +123,7 @@ namespace snmalloc
|
||||
template<typename Fn>
|
||||
static R execute(void* p, Args... args)
|
||||
{
|
||||
return (*static_cast<std::add_pointer_t<Fn>>(p))(args...);
|
||||
return (*static_cast<stl::add_pointer_t<Fn>>(p))(args...);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace snmalloc
|
||||
*/
|
||||
template<typename T>
|
||||
SNMALLOC_FAST_PATH_INLINE uintptr_t
|
||||
unsafe_to_uintptr(std::enable_if_t<true, T>* p)
|
||||
unsafe_to_uintptr(stl::enable_if_t<true, T>* p)
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(p);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace snmalloc
|
||||
} -> ConceptSameModRef<const typename Rep::Contents>;
|
||||
{
|
||||
typename Rep::Handle{const_cast<
|
||||
std::remove_const_t<std::remove_reference_t<decltype(Rep::root)>>*>(
|
||||
stl::remove_const_t<stl::remove_reference_t<decltype(Rep::root)>>*>(
|
||||
&Rep::root)}
|
||||
} -> ConceptSame<typename Rep::Handle>;
|
||||
};
|
||||
@@ -70,7 +70,7 @@ namespace snmalloc
|
||||
RBRepTypes<Rep> //
|
||||
&& RBRepMethods<Rep> //
|
||||
&&
|
||||
ConceptSame<decltype(Rep::null), std::add_const_t<typename Rep::Contents>>;
|
||||
ConceptSame<decltype(Rep::null), stl::add_const_t<typename Rep::Contents>>;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -156,7 +156,7 @@ namespace snmalloc
|
||||
};
|
||||
|
||||
// Root field of the tree
|
||||
typename std::remove_const_t<std::remove_reference_t<decltype(Rep::root)>>
|
||||
typename stl::remove_const_t<stl::remove_reference_t<decltype(Rep::root)>>
|
||||
root{Rep::root};
|
||||
|
||||
static ChildRef get_dir(bool direction, K k)
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#include "../aal/aal.h"
|
||||
#include "../ds_core/ds_core.h"
|
||||
#include "snmalloc/stl/type_traits.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
@@ -98,7 +98,7 @@ namespace snmalloc
|
||||
SNMALLOC_FAST_PATH bool is_empty()
|
||||
{
|
||||
static_assert(
|
||||
std::is_same_v<Node, decltype(std::declval<T>().node)>,
|
||||
stl::is_same_v<Node, decltype(std::declval<T>().node)>,
|
||||
"T->node must be Node for T");
|
||||
head.invariant();
|
||||
return head.next == &head;
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace snmalloc::libc
|
||||
return ThreadAlloc::get().get_client_meta_data(p);
|
||||
}
|
||||
|
||||
inline std::add_const_t<typename snmalloc::Alloc::Config::ClientMeta::DataRef>
|
||||
inline stl::add_const_t<typename snmalloc::Alloc::Config::ClientMeta::DataRef>
|
||||
get_client_meta_data_const(void* p)
|
||||
{
|
||||
return ThreadAlloc::get().get_client_meta_data_const(p);
|
||||
|
||||
@@ -418,7 +418,7 @@ namespace snmalloc
|
||||
#elif defined(__powerpc64__)
|
||||
PPC64Arch
|
||||
#else
|
||||
std::conditional_t<
|
||||
stl::conditional_t<
|
||||
aal_supports<StrictProvenance>,
|
||||
GenericStrictProvenance,
|
||||
GenericArch>
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace snmalloc
|
||||
*
|
||||
*/
|
||||
template<typename Config>
|
||||
concept IsConfig = std::is_base_of<CommonConfig, Config>::value &&
|
||||
concept IsConfig = stl::is_base_of_v<CommonConfig, Config> &&
|
||||
IsPAL<typename Config::Pal> &&
|
||||
IsBackend<typename Config::LocalState,
|
||||
typename Config::PagemapEntry,
|
||||
|
||||
@@ -43,8 +43,8 @@ namespace snmalloc
|
||||
SNMALLOC_CONCEPT(IsConfigDomestication) Config,
|
||||
typename T,
|
||||
SNMALLOC_CONCEPT(capptr::IsBound) B>
|
||||
constexpr SNMALLOC_FAST_PATH auto has_domesticate(int) -> std::enable_if_t<
|
||||
std::is_same_v<
|
||||
constexpr SNMALLOC_FAST_PATH auto has_domesticate(int) -> stl::enable_if_t<
|
||||
stl::is_same_v<
|
||||
decltype(Config::capptr_domesticate(
|
||||
std::declval<typename Config::LocalState*>(),
|
||||
std::declval<CapPtr<T, B>>())),
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace snmalloc
|
||||
* `init_message_queue`.
|
||||
*/
|
||||
template<SNMALLOC_CONCEPT(IsConfigLazy) Config>
|
||||
class CoreAllocator : public std::conditional_t<
|
||||
class CoreAllocator : public stl::conditional_t<
|
||||
Config::Options.CoreAllocIsPoolAllocated,
|
||||
Pooled<CoreAllocator<Config>>,
|
||||
Empty>
|
||||
@@ -78,7 +78,7 @@ namespace snmalloc
|
||||
* Message queue for allocations being returned to this
|
||||
* allocator
|
||||
*/
|
||||
std::conditional_t<
|
||||
stl::conditional_t<
|
||||
Config::Options.IsQueueInline,
|
||||
RemoteAllocator,
|
||||
RemoteAllocator*>
|
||||
@@ -95,7 +95,7 @@ namespace snmalloc
|
||||
* core allocator owns the local state or indirect if it is owned
|
||||
* externally.
|
||||
*/
|
||||
std::conditional_t<
|
||||
stl::conditional_t<
|
||||
Config::Options.CoreAllocOwnsLocalState,
|
||||
LocalState,
|
||||
LocalState*>
|
||||
@@ -661,7 +661,7 @@ namespace snmalloc
|
||||
*/
|
||||
template<
|
||||
typename Config_ = Config,
|
||||
typename = std::enable_if_t<Config_::Options.CoreAllocOwnsLocalState>>
|
||||
typename = stl::enable_if_t<Config_::Options.CoreAllocOwnsLocalState>>
|
||||
CoreAllocator(Range<capptr::bounds::Alloc>& spare)
|
||||
{
|
||||
init(spare);
|
||||
@@ -676,7 +676,7 @@ namespace snmalloc
|
||||
*/
|
||||
template<
|
||||
typename Config_ = Config,
|
||||
typename = std::enable_if_t<!Config_::Options.CoreAllocOwnsLocalState>>
|
||||
typename = stl::enable_if_t<!Config_::Options.CoreAllocOwnsLocalState>>
|
||||
CoreAllocator(
|
||||
Range<capptr::bounds::Alloc>& spare,
|
||||
LocalCache<Config_>* cache,
|
||||
@@ -691,7 +691,7 @@ namespace snmalloc
|
||||
* configure the message queue for use.
|
||||
*/
|
||||
template<bool InlineQueue = Config::Options.IsQueueInline>
|
||||
std::enable_if_t<!InlineQueue> init_message_queue(RemoteAllocator* q)
|
||||
stl::enable_if_t<!InlineQueue> init_message_queue(RemoteAllocator* q)
|
||||
{
|
||||
remote_alloc = q;
|
||||
init_message_queue();
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#include "../ds/ds.h"
|
||||
#include "../pal/pal.h"
|
||||
#include "snmalloc/stl/type_traits.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace snmalloc
|
||||
};
|
||||
|
||||
SNMALLOC_NO_UNIQUE_ADDRESS
|
||||
std::conditional_t<mitigations(freelist_backward_edge), Prev, Empty>
|
||||
stl::conditional_t<mitigations(freelist_backward_edge), Prev, Empty>
|
||||
prev{};
|
||||
|
||||
public:
|
||||
@@ -377,7 +377,7 @@ namespace snmalloc
|
||||
"Free Object View must be domesticated, justifying raw pointers");
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
stl::is_same_v<
|
||||
typename BQueue::template with_wildness<
|
||||
capptr::dimension::Wildness::Tame>,
|
||||
BView>,
|
||||
@@ -554,7 +554,7 @@ namespace snmalloc
|
||||
};
|
||||
|
||||
using IterBase =
|
||||
std::conditional_t<mitigations(freelist_backward_edge), Prev, NoPrev>;
|
||||
stl::conditional_t<mitigations(freelist_backward_edge), Prev, NoPrev>;
|
||||
|
||||
/**
|
||||
* Used to iterate a free list in object space.
|
||||
@@ -596,7 +596,7 @@ namespace snmalloc
|
||||
};
|
||||
|
||||
SNMALLOC_NO_UNIQUE_ADDRESS
|
||||
std::conditional_t<
|
||||
stl::conditional_t<
|
||||
mitigations(freelist_forward_edge) ||
|
||||
mitigations(freelist_backward_edge),
|
||||
KeyTweak,
|
||||
@@ -774,7 +774,7 @@ namespace snmalloc
|
||||
* lists, which will be randomised at the other end.
|
||||
*/
|
||||
template<bool RANDOM_ = RANDOM>
|
||||
std::enable_if_t<!RANDOM_> add(
|
||||
stl::enable_if_t<!RANDOM_> add(
|
||||
Object::BHeadPtr<BView, BQueue> n,
|
||||
const FreeListKey& key,
|
||||
address_t key_tweak)
|
||||
@@ -896,14 +896,14 @@ namespace snmalloc
|
||||
}
|
||||
|
||||
template<bool RANDOM_ = RANDOM>
|
||||
std::enable_if_t<!RANDOM_, size_t> extract_segment_length()
|
||||
stl::enable_if_t<!RANDOM_, size_t> extract_segment_length()
|
||||
{
|
||||
static_assert(RANDOM_ == RANDOM, "Don't set SFINAE parameter!");
|
||||
return length[0];
|
||||
}
|
||||
|
||||
template<bool RANDOM_ = RANDOM>
|
||||
std::enable_if_t<
|
||||
stl::enable_if_t<
|
||||
!RANDOM_,
|
||||
std::pair<
|
||||
Object::BHeadPtr<BView, BQueue>,
|
||||
|
||||
@@ -853,7 +853,7 @@ namespace snmalloc
|
||||
* @brief Get the client meta data for the snmalloc allocation covering this
|
||||
* pointer.
|
||||
*/
|
||||
std::add_const_t<typename Config::ClientMeta::DataRef>
|
||||
stl::add_const_t<typename Config::ClientMeta::DataRef>
|
||||
get_client_meta_data_const(void* p)
|
||||
{
|
||||
const PagemapEntry& entry =
|
||||
|
||||
@@ -454,7 +454,7 @@ namespace snmalloc
|
||||
smallsizeclass_t sizeclass, address_t slab, const FreeListKey& key)
|
||||
{
|
||||
static_assert(
|
||||
std::is_base_of<FrontendSlabMetadata_Trait, BackendType>::value,
|
||||
stl::is_base_of_v<FrontendSlabMetadata_Trait, BackendType>,
|
||||
"Template should be a subclass of FrontendSlabMetadata");
|
||||
free_queue.init(slab, key, this->as_key_tweak());
|
||||
// Set up meta data as if the entire slab has been turned into a free
|
||||
@@ -629,7 +629,7 @@ namespace snmalloc
|
||||
{
|
||||
auto& key = freelist::Object::key_root;
|
||||
|
||||
std::remove_reference_t<decltype(fast_free_list)> tmp_fl;
|
||||
stl::remove_reference_t<decltype(fast_free_list)> tmp_fl;
|
||||
|
||||
auto remaining =
|
||||
meta->free_queue.close(tmp_fl, key, meta->as_key_tweak());
|
||||
@@ -707,7 +707,7 @@ namespace snmalloc
|
||||
* Ensure that the template parameter is valid.
|
||||
*/
|
||||
static_assert(
|
||||
std::is_convertible_v<SlabMetadataType, FrontendSlabMetadata_Trait>,
|
||||
stl::is_convertible_v<SlabMetadataType, FrontendSlabMetadata_Trait>,
|
||||
"The front end requires that the back end provides slab metadata that is "
|
||||
"compatible with the front-end's structure");
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ namespace snmalloc
|
||||
static_assert(offsetof(SingletonRemoteMessage, message_link) == 0);
|
||||
};
|
||||
|
||||
using RemoteMessage = std::conditional_t<
|
||||
using RemoteMessage = stl::conditional_t<
|
||||
(DEALLOC_BATCH_RINGS > 0),
|
||||
BatchedRemoteMessage,
|
||||
SingletonRemoteMessage>;
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace snmalloc
|
||||
};
|
||||
|
||||
template<typename Config>
|
||||
using RemoteDeallocCacheBatchingImpl = std::conditional_t<
|
||||
using RemoteDeallocCacheBatchingImpl = stl::conditional_t<
|
||||
(DEALLOC_BATCH_RINGS > 0),
|
||||
RemoteDeallocCacheBatching<Config, DEALLOC_BATCH_RINGS>,
|
||||
RemoteDeallocCacheNoBatching<Config>>;
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace snmalloc
|
||||
typename AAL = Aal,
|
||||
typename T,
|
||||
SNMALLOC_CONCEPT(capptr::IsBound) B>
|
||||
static inline typename std::enable_if_t<
|
||||
static inline typename stl::enable_if_t<
|
||||
!aal_supports<StrictProvenance, AAL>,
|
||||
CapPtr<T, capptr::user_address_control_type<B>>>
|
||||
capptr_to_user_address_control(CapPtr<T, B> p)
|
||||
@@ -99,7 +99,7 @@ namespace snmalloc
|
||||
typename AAL = Aal,
|
||||
typename T,
|
||||
SNMALLOC_CONCEPT(capptr::IsBound) B>
|
||||
static SNMALLOC_FAST_PATH typename std::enable_if_t<
|
||||
static SNMALLOC_FAST_PATH typename stl::enable_if_t<
|
||||
aal_supports<StrictProvenance, AAL>,
|
||||
CapPtr<T, capptr::user_address_control_type<B>>>
|
||||
capptr_to_user_address_control(CapPtr<T, B> p)
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace snmalloc
|
||||
template<typename PAL>
|
||||
concept IsPAL_static_features =
|
||||
requires() {
|
||||
typename std::integral_constant<uint64_t, PAL::pal_features>;
|
||||
typename stl::integral_constant<uint64_t, PAL::pal_features>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -30,8 +30,8 @@ namespace snmalloc
|
||||
template<typename PAL>
|
||||
concept IsPAL_static_sizes =
|
||||
requires() {
|
||||
typename std::integral_constant<std::size_t, PAL::address_bits>;
|
||||
typename std::integral_constant<std::size_t, PAL::page_size>;
|
||||
typename stl::integral_constant<std::size_t, PAL::address_bits>;
|
||||
typename stl::integral_constant<std::size_t, PAL::page_size>;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace snmalloc
|
||||
stl::Atomic<T*> elements{nullptr};
|
||||
|
||||
static_assert(
|
||||
std::is_same<decltype(T::pal_next), stl::Atomic<T*>>::value,
|
||||
stl::is_same_v<decltype(T::pal_next), stl::Atomic<T*>>,
|
||||
"Required pal_next type.");
|
||||
|
||||
public:
|
||||
|
||||
46
src/snmalloc/stl/cxx/type_traits.h
Normal file
46
src/snmalloc/stl/cxx/type_traits.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
namespace stl
|
||||
{
|
||||
using std::add_const_t;
|
||||
using std::add_lvalue_reference_t;
|
||||
using std::add_pointer_t;
|
||||
using std::add_rvalue_reference_t;
|
||||
using std::bool_constant;
|
||||
using std::conditional;
|
||||
using std::conditional_t;
|
||||
using std::decay;
|
||||
using std::decay_t;
|
||||
using std::enable_if;
|
||||
using std::enable_if_t;
|
||||
using std::false_type;
|
||||
using std::has_unique_object_representations_v;
|
||||
using std::integral_constant;
|
||||
using std::is_array_v;
|
||||
using std::is_base_of_v;
|
||||
using std::is_convertible_v;
|
||||
using std::is_copy_assignable_v;
|
||||
using std::is_copy_constructible_v;
|
||||
using std::is_function_v;
|
||||
using std::is_integral;
|
||||
using std::is_integral_v;
|
||||
using std::is_move_assignable_v;
|
||||
using std::is_move_constructible_v;
|
||||
using std::is_same;
|
||||
using std::is_same_v;
|
||||
using std::is_trivially_copyable_v;
|
||||
using std::remove_all_extents_t;
|
||||
using std::remove_const_t;
|
||||
using std::remove_cv;
|
||||
using std::remove_cv_t;
|
||||
using std::remove_extent_t;
|
||||
using std::remove_reference;
|
||||
using std::remove_reference_t;
|
||||
using std::true_type;
|
||||
using std::void_t;
|
||||
} // namespace stl
|
||||
} // namespace snmalloc
|
||||
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "snmalloc/stl/type_traits.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <type_traits> // TODO: switch the vendored headers when we have them.
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
@@ -29,15 +30,15 @@ namespace snmalloc
|
||||
class Atomic
|
||||
{
|
||||
static_assert(
|
||||
std::is_trivially_copyable_v<T> && std::is_copy_constructible_v<T> &&
|
||||
std::is_move_constructible_v<T> && std::is_copy_assignable_v<T> &&
|
||||
std::is_move_assignable_v<T>,
|
||||
stl::is_trivially_copyable_v<T> && stl::is_copy_constructible_v<T> &&
|
||||
stl::is_move_constructible_v<T> && stl::is_copy_assignable_v<T> &&
|
||||
stl::is_move_assignable_v<T>,
|
||||
"Atomic<T> requires T to be trivially copyable, copy "
|
||||
"constructible, move constructible, copy assignable, "
|
||||
"and move assignable.");
|
||||
|
||||
static_assert(
|
||||
std::has_unique_object_representations_v<T>,
|
||||
stl::has_unique_object_representations_v<T>,
|
||||
"vendored Atomic only supports types with unique object "
|
||||
"representations");
|
||||
|
||||
@@ -180,48 +181,48 @@ namespace snmalloc
|
||||
SNMALLOC_FAST_PATH T
|
||||
fetch_add(T increment, MemoryOrder mem_ord = MemoryOrder::SEQ_CST)
|
||||
{
|
||||
static_assert(std::is_integral_v<T>, "T must be an integral type.");
|
||||
static_assert(stl::is_integral_v<T>, "T must be an integral type.");
|
||||
return __atomic_fetch_add(addressof(val), increment, order(mem_ord));
|
||||
}
|
||||
|
||||
SNMALLOC_FAST_PATH T
|
||||
fetch_or(T mask, MemoryOrder mem_ord = MemoryOrder::SEQ_CST)
|
||||
{
|
||||
static_assert(std::is_integral_v<T>, "T must be an integral type.");
|
||||
static_assert(stl::is_integral_v<T>, "T must be an integral type.");
|
||||
return __atomic_fetch_or(addressof(val), mask, order(mem_ord));
|
||||
}
|
||||
|
||||
SNMALLOC_FAST_PATH T
|
||||
fetch_and(T mask, MemoryOrder mem_ord = MemoryOrder::SEQ_CST)
|
||||
{
|
||||
static_assert(std::is_integral_v<T>, "T must be an integral type.");
|
||||
static_assert(stl::is_integral_v<T>, "T must be an integral type.");
|
||||
return __atomic_fetch_and(addressof(val), mask, order(mem_ord));
|
||||
}
|
||||
|
||||
SNMALLOC_FAST_PATH T
|
||||
fetch_sub(T decrement, MemoryOrder mem_ord = MemoryOrder::SEQ_CST)
|
||||
{
|
||||
static_assert(std::is_integral_v<T>, "T must be an integral type.");
|
||||
static_assert(stl::is_integral_v<T>, "T must be an integral type.");
|
||||
return __atomic_fetch_sub(addressof(val), decrement, order(mem_ord));
|
||||
}
|
||||
|
||||
SNMALLOC_FAST_PATH T operator++()
|
||||
{
|
||||
static_assert(std::is_integral_v<T>, "T must be an integral type.");
|
||||
static_assert(stl::is_integral_v<T>, "T must be an integral type.");
|
||||
return __atomic_add_fetch(
|
||||
addressof(val), 1, order(MemoryOrder::SEQ_CST));
|
||||
}
|
||||
|
||||
SNMALLOC_FAST_PATH const T operator++(int)
|
||||
{
|
||||
static_assert(std::is_integral_v<T>, "T must be an integral type.");
|
||||
static_assert(stl::is_integral_v<T>, "T must be an integral type.");
|
||||
return __atomic_fetch_add(
|
||||
addressof(val), 1, order(MemoryOrder::SEQ_CST));
|
||||
}
|
||||
|
||||
SNMALLOC_FAST_PATH T operator-=(T decrement)
|
||||
{
|
||||
static_assert(std::is_integral_v<T>, "T must be an integral type.");
|
||||
static_assert(stl::is_integral_v<T>, "T must be an integral type.");
|
||||
return __atomic_sub_fetch(
|
||||
addressof(val), decrement, order(MemoryOrder::SEQ_CST));
|
||||
}
|
||||
|
||||
394
src/snmalloc/stl/gnu/type_traits.h
Normal file
394
src/snmalloc/stl/gnu/type_traits.h
Normal file
@@ -0,0 +1,394 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
namespace stl
|
||||
{
|
||||
/**
|
||||
* Type identity metafunction.
|
||||
*/
|
||||
template<typename T>
|
||||
struct type_identity
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using type_identity_t = typename type_identity<T>::type;
|
||||
|
||||
/**
|
||||
* Integral constant.
|
||||
*/
|
||||
template<typename T, T v>
|
||||
struct integral_constant
|
||||
{
|
||||
using value_type = T;
|
||||
static constexpr T value = v;
|
||||
};
|
||||
|
||||
template<bool B>
|
||||
using bool_constant = integral_constant<bool, B>;
|
||||
|
||||
using true_type = bool_constant<true>;
|
||||
using false_type = bool_constant<false>;
|
||||
|
||||
/**
|
||||
* Remove CV qualifiers.
|
||||
*/
|
||||
template<class T>
|
||||
struct remove_cv : type_identity<T>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct remove_cv<const T> : type_identity<T>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct remove_cv<volatile T> : type_identity<T>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct remove_cv<const volatile T> : type_identity<T>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
using remove_cv_t = typename remove_cv<T>::type;
|
||||
|
||||
/**
|
||||
* Type equality.
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
struct is_same : false_type
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
struct is_same<T, T> : true_type
|
||||
{};
|
||||
|
||||
template<typename T, typename U>
|
||||
inline constexpr bool is_same_v = is_same<T, U>::value;
|
||||
|
||||
/**
|
||||
* Is integral type.
|
||||
*/
|
||||
template<typename T>
|
||||
struct is_integral
|
||||
{
|
||||
private:
|
||||
template<typename Head, typename... Args>
|
||||
static constexpr bool is_unqualified_any_of()
|
||||
{
|
||||
return (... || is_same_v<remove_cv_t<Head>, Args>);
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr bool value = is_unqualified_any_of<
|
||||
T,
|
||||
#ifdef __SIZEOF_INT128__
|
||||
__int128_t,
|
||||
__uint128_t,
|
||||
#endif
|
||||
char,
|
||||
signed char,
|
||||
unsigned char,
|
||||
short,
|
||||
unsigned short,
|
||||
int,
|
||||
unsigned int,
|
||||
long,
|
||||
unsigned long,
|
||||
long long,
|
||||
unsigned long long,
|
||||
bool>();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_integral_v = is_integral<T>::value;
|
||||
|
||||
/**
|
||||
* Remove all array extents.
|
||||
*/
|
||||
#if __has_builtin(__remove_all_extents)
|
||||
template<typename T>
|
||||
using remove_all_extents_t = __remove_all_extents(T);
|
||||
#else
|
||||
template<class T>
|
||||
struct remove_all_extents
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_all_extents<T[]>
|
||||
{
|
||||
using type = typename remove_all_extents<T>::type;
|
||||
};
|
||||
|
||||
template<class T, size_t N>
|
||||
struct remove_all_extents<T[N]>
|
||||
{
|
||||
using type = typename remove_all_extents<T>::type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using remove_all_extents_t = typename remove_all_extents<T>::type;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* void_t
|
||||
*/
|
||||
template<typename... Ts>
|
||||
using void_t = typename type_identity<void>::type;
|
||||
|
||||
/**
|
||||
* Has unique object representations.
|
||||
*/
|
||||
/* remove_all_extents_t is needed due to clang's behavior */
|
||||
template<class T>
|
||||
inline constexpr bool has_unique_object_representations_v =
|
||||
__has_unique_object_representations(remove_all_extents_t<T>);
|
||||
|
||||
/**
|
||||
* enable_if
|
||||
*/
|
||||
template<bool B, typename T = void>
|
||||
struct enable_if;
|
||||
|
||||
template<typename T>
|
||||
struct enable_if<true, T> : type_identity<T>
|
||||
{};
|
||||
|
||||
template<bool B, typename T = void>
|
||||
using enable_if_t = typename enable_if<B, T>::type;
|
||||
|
||||
/**
|
||||
* conditional
|
||||
*/
|
||||
|
||||
template<bool B, typename T, typename F>
|
||||
struct conditional : type_identity<T>
|
||||
{};
|
||||
|
||||
template<typename T, typename F>
|
||||
struct conditional<false, T, F> : type_identity<F>
|
||||
{};
|
||||
|
||||
template<bool B, typename T, typename F>
|
||||
using conditional_t = typename conditional<B, T, F>::type;
|
||||
|
||||
/**
|
||||
* add_lvalue_reference/add_rvalue_reference
|
||||
*/
|
||||
#if __has_builtin(__add_lvalue_reference)
|
||||
template<class T>
|
||||
using add_lvalue_reference_t = __add_lvalue_reference(T);
|
||||
#else
|
||||
template<class T> // Note that `cv void&` is a substitution failure
|
||||
auto __add_lvalue_reference_impl(int) -> type_identity<T&>;
|
||||
template<class T> // Handle T = cv void case
|
||||
auto __add_lvalue_reference_impl(...) -> type_identity<T>;
|
||||
|
||||
template<class T>
|
||||
struct add_lvalue_reference : decltype(__add_lvalue_reference_impl<T>(0))
|
||||
{};
|
||||
template<class T>
|
||||
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__add_rvalue_reference)
|
||||
template<class T>
|
||||
using add_rvalue_reference_t = __add_rvalue_reference(T);
|
||||
#else
|
||||
template<class T>
|
||||
auto __add_rvalue_reference_impl(int) -> type_identity<T&&>;
|
||||
template<class T>
|
||||
auto __add_rvalue_referenc_impl(...) -> type_identity<T>;
|
||||
|
||||
template<class T>
|
||||
struct add_rvalue_reference : decltype(__add_rvalue_reference_impl<T>(0))
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* remove_reference
|
||||
*/
|
||||
template<class T>
|
||||
struct remove_reference : type_identity<T>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct remove_reference<T&> : type_identity<T>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct remove_reference<T&&> : type_identity<T>
|
||||
{};
|
||||
template<class T>
|
||||
using remove_reference_t = typename remove_reference<T>::type;
|
||||
|
||||
/**
|
||||
* add_pointer
|
||||
*/
|
||||
#if __has_builtin(__add_pointer)
|
||||
template<class T>
|
||||
using add_pointer_t = __add_pointer(T);
|
||||
#else
|
||||
template<class T>
|
||||
auto __add_pointer_impl(int) -> type_identity<remove_reference_t<T>*>;
|
||||
template<class T>
|
||||
auto __add_pointer_impl(...) -> type_identity<T>;
|
||||
|
||||
template<class T>
|
||||
struct add_pointer : decltype(__add_pointer_impl<T>(0))
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
using add_pointer_t = typename add_pointer<T>::type;
|
||||
#endif
|
||||
/**
|
||||
* is_array
|
||||
*/
|
||||
template<class T>
|
||||
inline constexpr bool is_array_v = __is_array(T);
|
||||
|
||||
/**
|
||||
* is_function
|
||||
*/
|
||||
template<typename T>
|
||||
inline constexpr bool is_function_v = __is_function(T);
|
||||
|
||||
/**
|
||||
* remove_extent
|
||||
*/
|
||||
|
||||
#if __has_builtin(__remove_extent)
|
||||
template<class T>
|
||||
using remove_extent_t = __remove_extent(T);
|
||||
#else
|
||||
template<class T>
|
||||
struct remove_extent
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_extent<T[]>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<class T, size_t N>
|
||||
struct remove_extent<T[N]>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using remove_extent_t = typename remove_extent<T>::type;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* decay
|
||||
*/
|
||||
#if __has_builtin(__decay)
|
||||
template<class T>
|
||||
using decay_t = __decay(T);
|
||||
#else
|
||||
template<class T>
|
||||
class decay
|
||||
{
|
||||
using U = remove_reference_t<T>;
|
||||
|
||||
public:
|
||||
using type = conditional_t<
|
||||
is_array_v<U>,
|
||||
add_pointer_t<remove_extent_t<U>>,
|
||||
conditional_t<is_function_v<U>, add_pointer_t<U>, remove_cv_t<U>>>;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using decay_t = typename decay<T>::type;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* is_copy_assignable
|
||||
*/
|
||||
template<class T>
|
||||
constexpr bool is_copy_assignable_v = __is_assignable(
|
||||
add_lvalue_reference_t<T>, add_lvalue_reference_t<const T>);
|
||||
|
||||
/**
|
||||
* is_copy_constructible
|
||||
*/
|
||||
template<class T>
|
||||
inline constexpr bool is_copy_constructible_v =
|
||||
__is_constructible(T, add_lvalue_reference_t<const T>);
|
||||
|
||||
/**
|
||||
* is_move_assignable
|
||||
*/
|
||||
template<class T>
|
||||
constexpr bool is_move_assignable_v =
|
||||
__is_assignable(add_lvalue_reference_t<T>, add_lvalue_reference_t<T>);
|
||||
|
||||
/**
|
||||
* is_move_constructible
|
||||
*/
|
||||
template<class T>
|
||||
inline constexpr bool is_move_constructible_v =
|
||||
__is_constructible(T, add_rvalue_reference_t<T>);
|
||||
|
||||
/**
|
||||
* is_convertible
|
||||
*/
|
||||
template<class From, class To>
|
||||
inline constexpr bool is_convertible_v = __is_convertible(From, To);
|
||||
|
||||
/**
|
||||
* is_base_of
|
||||
*/
|
||||
template<class Base, class Derived>
|
||||
inline constexpr bool is_base_of_v = __is_base_of(Base, Derived);
|
||||
|
||||
/**
|
||||
* is_trivially_copyable
|
||||
*/
|
||||
template<class T>
|
||||
inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(T);
|
||||
|
||||
/**
|
||||
* remove_const
|
||||
*/
|
||||
#if __has_builtin(__remove_const)
|
||||
template<class T>
|
||||
using remove_const_t = __remove_const(T);
|
||||
#else
|
||||
template<class T>
|
||||
struct remove_const
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_const<const T>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using remove_const_t = typename remove_const<T>::type;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* add_const
|
||||
*/
|
||||
template<class T>
|
||||
using add_const_t = const T;
|
||||
|
||||
} // namespace stl
|
||||
} // namespace snmalloc
|
||||
9
src/snmalloc/stl/type_traits.h
Normal file
9
src/snmalloc/stl/type_traits.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "snmalloc/stl/common.h"
|
||||
|
||||
#if SNMALLOC_USE_SELF_VENDORED_STL
|
||||
# include "snmalloc/stl/gnu/type_traits.h"
|
||||
#else
|
||||
# include "snmalloc/stl/cxx/type_traits.h"
|
||||
#endif
|
||||
Reference in New Issue
Block a user