Squashed 'external/entt/entt/' content from commit fef92113

git-subtree-dir: external/entt/entt
git-subtree-split: fef921132cae7588213d0f9bcd2fb9c8ffd8b7fc
This commit is contained in:
2023-07-25 11:29:51 +02:00
commit 5c7231b7a3
242 changed files with 146004 additions and 0 deletions

View File

@ -0,0 +1,98 @@
#include <array>
#include <vector>
#include <gtest/gtest.h>
#include <entt/core/algorithm.hpp>
struct boxed_int {
int value;
};
TEST(Algorithm, StdSort) {
// well, I'm pretty sure it works, it's std::sort!!
std::array<int, 5> arr{{4, 1, 3, 2, 0}};
entt::std_sort sort;
sort(arr.begin(), arr.end());
for(auto i = 0u; i < (arr.size() - 1u); ++i) {
ASSERT_LT(arr[i], arr[i + 1u]);
}
}
TEST(Algorithm, StdSortBoxedInt) {
// well, I'm pretty sure it works, it's std::sort!!
std::array<boxed_int, 6> arr{{{4}, {1}, {3}, {2}, {0}, {6}}};
entt::std_sort sort;
sort(arr.begin(), arr.end(), [](const auto &lhs, const auto &rhs) {
return lhs.value > rhs.value;
});
for(auto i = 0u; i < (arr.size() - 1u); ++i) {
ASSERT_GT(arr[i].value, arr[i + 1u].value);
}
}
TEST(Algorithm, InsertionSort) {
std::array<int, 5> arr{{4, 1, 3, 2, 0}};
entt::insertion_sort sort;
sort(arr.begin(), arr.end());
for(auto i = 0u; i < (arr.size() - 1u); ++i) {
ASSERT_LT(arr[i], arr[i + 1u]);
}
}
TEST(Algorithm, InsertionSortBoxedInt) {
std::array<boxed_int, 6> arr{{{4}, {1}, {3}, {2}, {0}, {6}}};
entt::insertion_sort sort;
sort(arr.begin(), arr.end(), [](const auto &lhs, const auto &rhs) {
return lhs.value > rhs.value;
});
for(auto i = 0u; i < (arr.size() - 1u); ++i) {
ASSERT_GT(arr[i].value, arr[i + 1u].value);
}
}
TEST(Algorithm, InsertionSortEmptyContainer) {
std::vector<int> vec{};
entt::insertion_sort sort;
// this should crash with asan enabled if we break the constraint
sort(vec.begin(), vec.end());
}
TEST(Algorithm, RadixSort) {
std::array<uint32_t, 5> arr{{4, 1, 3, 2, 0}};
entt::radix_sort<8, 32> sort;
sort(arr.begin(), arr.end(), [](const auto &value) {
return value;
});
for(auto i = 0u; i < (arr.size() - 1u); ++i) {
ASSERT_LT(arr[i], arr[i + 1u]);
}
}
TEST(Algorithm, RadixSortBoxedInt) {
std::array<boxed_int, 6> arr{{{4}, {1}, {3}, {2}, {0}, {6}}};
entt::radix_sort<2, 6> sort;
sort(arr.rbegin(), arr.rend(), [](const auto &instance) {
return instance.value;
});
for(auto i = 0u; i < (arr.size() - 1u); ++i) {
ASSERT_GT(arr[i].value, arr[i + 1u].value);
}
}
TEST(Algorithm, RadixSortEmptyContainer) {
std::vector<int> vec{};
entt::radix_sort<8, 32> sort;
// this should crash with asan enabled if we break the constraint
sort(vec.begin(), vec.end());
}

1466
test/entt/core/any.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,182 @@
#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include <entt/core/compressed_pair.hpp>
struct empty_type {};
struct move_only_type {
move_only_type()
: value{new int{99}} {}
move_only_type(int v)
: value{new int{v}} {}
~move_only_type() {
delete value;
}
move_only_type(const move_only_type &) = delete;
move_only_type &operator=(const move_only_type &) = delete;
move_only_type(move_only_type &&other) noexcept
: value{std::exchange(other.value, nullptr)} {}
move_only_type &operator=(move_only_type &&other) noexcept {
delete value;
value = std::exchange(other.value, nullptr);
return *this;
}
int *value;
};
struct non_default_constructible {
non_default_constructible(int v)
: value{v} {}
int value;
};
TEST(CompressedPair, Size) {
struct local {
int value;
empty_type empty;
};
static_assert(sizeof(entt::compressed_pair<int, int>) == sizeof(int[2u]));
static_assert(sizeof(entt::compressed_pair<empty_type, int>) == sizeof(int));
static_assert(sizeof(entt::compressed_pair<int, empty_type>) == sizeof(int));
static_assert(sizeof(entt::compressed_pair<int, empty_type>) < sizeof(local));
static_assert(sizeof(entt::compressed_pair<int, empty_type>) < sizeof(std::pair<int, empty_type>));
}
TEST(CompressedPair, ConstructCopyMove) {
static_assert(!std::is_default_constructible_v<entt::compressed_pair<non_default_constructible, empty_type>>);
static_assert(std::is_default_constructible_v<entt::compressed_pair<move_only_type, empty_type>>);
static_assert(std::is_copy_constructible_v<entt::compressed_pair<non_default_constructible, empty_type>>);
static_assert(!std::is_copy_constructible_v<entt::compressed_pair<move_only_type, empty_type>>);
static_assert(std::is_copy_assignable_v<entt::compressed_pair<non_default_constructible, empty_type>>);
static_assert(!std::is_copy_assignable_v<entt::compressed_pair<move_only_type, empty_type>>);
static_assert(std::is_move_constructible_v<entt::compressed_pair<move_only_type, empty_type>>);
static_assert(std::is_move_assignable_v<entt::compressed_pair<move_only_type, empty_type>>);
entt::compressed_pair copyable{non_default_constructible{42}, empty_type{}};
auto by_copy{copyable};
ASSERT_EQ(by_copy.first().value, 42);
by_copy.first().value = 3;
copyable = by_copy;
ASSERT_EQ(copyable.first().value, 3);
entt::compressed_pair<empty_type, move_only_type> movable{};
auto by_move{std::move(movable)};
ASSERT_EQ(*by_move.second().value, 99);
ASSERT_EQ(movable.second().value, nullptr);
*by_move.second().value = 3;
movable = std::move(by_move);
ASSERT_EQ(*movable.second().value, 3);
ASSERT_EQ(by_move.second().value, nullptr);
}
TEST(CompressedPair, PiecewiseConstruct) {
std::vector<int> vec{42};
entt::compressed_pair<empty_type, empty_type> empty{std::piecewise_construct, std::make_tuple(), std::make_tuple()};
entt::compressed_pair<std::vector<int>, std::size_t> pair{std::piecewise_construct, std::forward_as_tuple(std::move(vec)), std::make_tuple(sizeof(empty))};
ASSERT_EQ(pair.first().size(), 1u);
ASSERT_EQ(pair.second(), sizeof(empty));
ASSERT_EQ(vec.size(), 0u);
}
TEST(CompressedPair, DeductionGuide) {
int value = 42;
empty_type empty{};
entt::compressed_pair pair{value, 3};
static_assert(std::is_same_v<decltype(entt::compressed_pair{empty_type{}, empty}), entt::compressed_pair<empty_type, empty_type>>);
ASSERT_TRUE((std::is_same_v<decltype(pair), entt::compressed_pair<int, int>>));
ASSERT_EQ(pair.first(), 42);
ASSERT_EQ(pair.second(), 3);
}
TEST(CompressedPair, Getters) {
entt::compressed_pair pair{3, empty_type{}};
const auto &cpair = pair;
static_assert(std::is_same_v<decltype(pair.first()), int &>);
static_assert(std::is_same_v<decltype(pair.second()), empty_type &>);
static_assert(std::is_same_v<decltype(cpair.first()), const int &>);
static_assert(std::is_same_v<decltype(cpair.second()), const empty_type &>);
ASSERT_EQ(pair.first(), cpair.first());
ASSERT_EQ(&pair.second(), &cpair.second());
}
TEST(CompressedPair, Swap) {
entt::compressed_pair pair{1, 2};
entt::compressed_pair other{3, 4};
swap(pair, other);
ASSERT_EQ(pair.first(), 3);
ASSERT_EQ(pair.second(), 4);
ASSERT_EQ(other.first(), 1);
ASSERT_EQ(other.second(), 2);
pair.swap(other);
ASSERT_EQ(pair.first(), 1);
ASSERT_EQ(pair.second(), 2);
ASSERT_EQ(other.first(), 3);
ASSERT_EQ(other.second(), 4);
}
TEST(CompressedPair, Get) {
entt::compressed_pair pair{1, 2};
ASSERT_EQ(pair.get<0>(), 1);
ASSERT_EQ(pair.get<1>(), 2);
ASSERT_EQ(&pair.get<0>(), &pair.first());
ASSERT_EQ(&pair.get<1>(), &pair.second());
auto &&[first, second] = pair;
ASSERT_EQ(first, 1);
ASSERT_EQ(second, 2);
first = 3;
second = 4;
ASSERT_EQ(pair.first(), 3);
ASSERT_EQ(pair.second(), 4);
auto &[cfirst, csecond] = std::as_const(pair);
ASSERT_EQ(cfirst, 3);
ASSERT_EQ(csecond, 4);
static_assert(std::is_same_v<decltype(cfirst), const int>);
static_assert(std::is_same_v<decltype(csecond), const int>);
auto [tfirst, tsecond] = entt::compressed_pair{9, 99};
ASSERT_EQ(tfirst, 9);
ASSERT_EQ(tsecond, 99);
static_assert(std::is_same_v<decltype(cfirst), const int>);
static_assert(std::is_same_v<decltype(csecond), const int>);
}

72
test/entt/core/enum.cpp Normal file
View File

@ -0,0 +1,72 @@
#include <cstdint>
#include <type_traits>
#include <gtest/gtest.h>
#include <entt/core/enum.hpp>
enum class detected {
foo = 0x01,
bar = 0x02,
quux = 0x04,
_entt_enum_as_bitmask
};
// small type on purpose
enum class registered : std::uint8_t {
foo = 0x01,
bar = 0x02,
quux = 0x04
};
template<>
struct entt::enum_as_bitmask<registered>
: std::true_type {};
template<typename Type>
struct Enum: testing::Test {
using type = Type;
};
using EnumTypes = ::testing::Types<detected, registered>;
TYPED_TEST_SUITE(Enum, EnumTypes, );
TYPED_TEST(Enum, Functionalities) {
using enum_type = typename TestFixture::type;
ASSERT_TRUE(!!((enum_type::foo | enum_type::bar) & enum_type::foo));
ASSERT_TRUE(!!((enum_type::foo | enum_type::bar) & enum_type::bar));
ASSERT_TRUE(!((enum_type::foo | enum_type::bar) & enum_type::quux));
ASSERT_TRUE(!!((enum_type::foo ^ enum_type::bar) & enum_type::foo));
ASSERT_TRUE(!((enum_type::foo ^ enum_type::foo) & enum_type::foo));
ASSERT_TRUE(!(~enum_type::foo & enum_type::foo));
ASSERT_TRUE(!!(~enum_type::foo & enum_type::bar));
ASSERT_TRUE(enum_type::foo == enum_type::foo);
ASSERT_TRUE(enum_type::foo != enum_type::bar);
enum_type value = enum_type::foo;
ASSERT_TRUE(!!(value & enum_type::foo));
ASSERT_TRUE(!(value & enum_type::bar));
ASSERT_TRUE(!(value & enum_type::quux));
value |= (enum_type::bar | enum_type::quux);
ASSERT_TRUE(!!(value & enum_type::foo));
ASSERT_TRUE(!!(value & enum_type::bar));
ASSERT_TRUE(!!(value & enum_type::quux));
value &= (enum_type::bar | enum_type::quux);
ASSERT_TRUE(!(value & enum_type::foo));
ASSERT_TRUE(!!(value & enum_type::bar));
ASSERT_TRUE(!!(value & enum_type::quux));
value ^= enum_type::bar;
ASSERT_TRUE(!(value & enum_type::foo));
ASSERT_TRUE(!(value & enum_type::bar));
ASSERT_TRUE(!!(value & enum_type::quux));
}

22
test/entt/core/family.cpp Normal file
View File

@ -0,0 +1,22 @@
#include <gtest/gtest.h>
#include <entt/core/family.hpp>
using a_family = entt::family<struct a_family_type>;
using another_family = entt::family<struct another_family_type>;
TEST(Family, Functionalities) {
auto t1 = a_family::value<int>;
auto t2 = a_family::value<int>;
auto t3 = a_family::value<char>;
auto t4 = another_family::value<double>;
ASSERT_EQ(t1, t2);
ASSERT_NE(t1, t3);
ASSERT_EQ(t1, t4);
}
TEST(Family, Uniqueness) {
ASSERT_NE(a_family::value<int>, a_family::value<int &>);
ASSERT_NE(a_family::value<int>, a_family::value<int &&>);
ASSERT_NE(a_family::value<int>, a_family::value<const int &>);
}

View File

@ -0,0 +1,224 @@
#include <cstdint>
#include <string>
#include <string_view>
#include <type_traits>
#include <gtest/gtest.h>
#include <entt/core/hashed_string.hpp>
template<typename>
struct foobar_t;
template<>
struct foobar_t<std::uint32_t> {
static constexpr auto value = 0xbf9cf968;
};
template<>
struct foobar_t<std::uint64_t> {
static constexpr auto value = 0x85944171f73967e8;
};
inline constexpr auto foobar_v = foobar_t<entt::id_type>::value;
TEST(BasicHashedString, DeductionGuide) {
static_assert(std::is_same_v<decltype(entt::basic_hashed_string{"foo"}), entt::hashed_string>);
static_assert(std::is_same_v<decltype(entt::basic_hashed_string{L"foo"}), entt::hashed_wstring>);
}
TEST(HashedString, Functionalities) {
using namespace entt::literals;
using hash_type = entt::hashed_string::hash_type;
const char *bar = "bar";
auto foo_hs = entt::hashed_string{"foo"};
auto bar_hs = entt::hashed_string{bar};
ASSERT_NE(static_cast<hash_type>(foo_hs), static_cast<hash_type>(bar_hs));
ASSERT_STREQ(static_cast<const char *>(foo_hs), "foo");
ASSERT_STREQ(static_cast<const char *>(bar_hs), bar);
ASSERT_STREQ(foo_hs.data(), "foo");
ASSERT_STREQ(bar_hs.data(), bar);
ASSERT_EQ(foo_hs.size(), 3u);
ASSERT_EQ(bar_hs.size(), 3u);
ASSERT_EQ(foo_hs, foo_hs);
ASSERT_NE(foo_hs, bar_hs);
entt::hashed_string hs{"foobar"};
ASSERT_EQ(static_cast<hash_type>(hs), foobar_v);
ASSERT_EQ(hs.value(), foobar_v);
ASSERT_EQ(foo_hs, "foo"_hs);
ASSERT_NE(bar_hs, "foo"_hs);
entt::hashed_string empty_hs{};
ASSERT_EQ(empty_hs, entt::hashed_string{});
ASSERT_NE(empty_hs, foo_hs);
empty_hs = foo_hs;
ASSERT_NE(empty_hs, entt::hashed_string{});
ASSERT_EQ(empty_hs, foo_hs);
}
TEST(HashedString, Empty) {
using hash_type = entt::hashed_string::hash_type;
entt::hashed_string hs{};
ASSERT_EQ(hs.size(), 0u);
ASSERT_EQ(static_cast<hash_type>(hs), hash_type{});
ASSERT_EQ(static_cast<const char *>(hs), nullptr);
}
TEST(HashedString, Correctness) {
const char *foobar = "foobar";
std::string_view view{"foobar__", 6};
ASSERT_EQ(entt::hashed_string{foobar}, foobar_v);
ASSERT_EQ((entt::hashed_string{view.data(), view.size()}), foobar_v);
ASSERT_EQ(entt::hashed_string{"foobar"}, foobar_v);
ASSERT_EQ(entt::hashed_string::value(foobar), foobar_v);
ASSERT_EQ(entt::hashed_string::value(view.data(), view.size()), foobar_v);
ASSERT_EQ(entt::hashed_string::value("foobar"), foobar_v);
ASSERT_EQ(entt::hashed_string{foobar}.size(), 6u);
ASSERT_EQ((entt::hashed_string{view.data(), view.size()}).size(), 6u);
ASSERT_EQ(entt::hashed_string{"foobar"}.size(), 6u);
}
TEST(HashedString, Order) {
using namespace entt::literals;
const entt::hashed_string lhs = "foo"_hs;
const entt::hashed_string rhs = "bar"_hs;
ASSERT_FALSE(lhs < lhs);
ASSERT_FALSE(rhs < rhs);
ASSERT_LT(rhs, lhs);
ASSERT_LE(rhs, lhs);
ASSERT_GT(lhs, rhs);
ASSERT_GE(lhs, rhs);
}
TEST(HashedString, Constexprness) {
using namespace entt::literals;
constexpr std::string_view view{"foobar__", 6};
static_assert(entt::hashed_string{"quux"} == "quux"_hs);
static_assert(entt::hashed_string{"foobar"} == foobar_v);
static_assert(entt::hashed_string::value("quux") == "quux"_hs);
static_assert(entt::hashed_string::value("foobar") == foobar_v);
static_assert(entt::hashed_string{"quux", 4} == "quux"_hs);
static_assert(entt::hashed_string{view.data(), view.size()} == foobar_v);
static_assert(entt::hashed_string::value("quux", 4) == "quux"_hs);
static_assert(entt::hashed_string::value(view.data(), view.size()) == foobar_v);
static_assert(entt::hashed_string{"bar"} < "foo"_hs);
static_assert(entt::hashed_string{"bar"} <= "bar"_hs);
static_assert(entt::hashed_string{"foo"} > "bar"_hs);
static_assert(entt::hashed_string{"foo"} >= "foo"_hs);
}
TEST(HashedWString, Functionalities) {
using namespace entt::literals;
using hash_type = entt::hashed_wstring::hash_type;
const wchar_t *bar = L"bar";
auto foo_hws = entt::hashed_wstring{L"foo"};
auto bar_hws = entt::hashed_wstring{bar};
ASSERT_NE(static_cast<hash_type>(foo_hws), static_cast<hash_type>(bar_hws));
ASSERT_STREQ(static_cast<const wchar_t *>(foo_hws), L"foo");
ASSERT_STREQ(static_cast<const wchar_t *>(bar_hws), bar);
ASSERT_STREQ(foo_hws.data(), L"foo");
ASSERT_STREQ(bar_hws.data(), bar);
ASSERT_EQ(foo_hws.size(), 3u);
ASSERT_EQ(bar_hws.size(), 3u);
ASSERT_EQ(foo_hws, foo_hws);
ASSERT_NE(foo_hws, bar_hws);
entt::hashed_wstring hws{L"foobar"};
ASSERT_EQ(static_cast<hash_type>(hws), foobar_v);
ASSERT_EQ(hws.value(), foobar_v);
ASSERT_EQ(foo_hws, L"foo"_hws);
ASSERT_NE(bar_hws, L"foo"_hws);
}
TEST(HashedWString, Empty) {
using hash_type = entt::hashed_wstring::hash_type;
entt::hashed_wstring hws{};
ASSERT_EQ(hws.size(), 0u);
ASSERT_EQ(static_cast<hash_type>(hws), hash_type{});
ASSERT_EQ(static_cast<const wchar_t *>(hws), nullptr);
}
TEST(HashedWString, Correctness) {
const wchar_t *foobar = L"foobar";
std::wstring_view view{L"foobar__", 6};
ASSERT_EQ(entt::hashed_wstring{foobar}, foobar_v);
ASSERT_EQ((entt::hashed_wstring{view.data(), view.size()}), foobar_v);
ASSERT_EQ(entt::hashed_wstring{L"foobar"}, foobar_v);
ASSERT_EQ(entt::hashed_wstring::value(foobar), foobar_v);
ASSERT_EQ(entt::hashed_wstring::value(view.data(), view.size()), foobar_v);
ASSERT_EQ(entt::hashed_wstring::value(L"foobar"), foobar_v);
ASSERT_EQ(entt::hashed_wstring{foobar}.size(), 6u);
ASSERT_EQ((entt::hashed_wstring{view.data(), view.size()}).size(), 6u);
ASSERT_EQ(entt::hashed_wstring{L"foobar"}.size(), 6u);
}
TEST(HashedWString, Order) {
using namespace entt::literals;
const entt::hashed_wstring lhs = L"foo"_hws;
const entt::hashed_wstring rhs = L"bar"_hws;
ASSERT_FALSE(lhs < lhs);
ASSERT_FALSE(rhs < rhs);
ASSERT_LT(rhs, lhs);
ASSERT_LE(rhs, lhs);
ASSERT_GT(lhs, rhs);
ASSERT_GE(lhs, rhs);
}
TEST(HashedWString, Constexprness) {
using namespace entt::literals;
constexpr std::wstring_view view{L"foobar__", 6};
static_assert(entt::hashed_wstring{L"quux"} == L"quux"_hws);
static_assert(entt::hashed_wstring{L"foobar"} == foobar_v);
static_assert(entt::hashed_wstring::value(L"quux") == L"quux"_hws);
static_assert(entt::hashed_wstring::value(L"foobar") == foobar_v);
static_assert(entt::hashed_wstring{L"quux", 4} == L"quux"_hws);
static_assert(entt::hashed_wstring{view.data(), view.size()} == foobar_v);
static_assert(entt::hashed_wstring::value(L"quux", 4) == L"quux"_hws);
static_assert(entt::hashed_wstring::value(view.data(), view.size()) == foobar_v);
static_assert(entt::hashed_wstring{L"bar"} < L"foo"_hws);
static_assert(entt::hashed_wstring{L"bar"} <= L"bar"_hws);
static_assert(entt::hashed_wstring{L"foo"} > L"bar"_hws);
static_assert(entt::hashed_wstring{L"foo"} >= L"foo"_hws);
}

31
test/entt/core/ident.cpp Normal file
View File

@ -0,0 +1,31 @@
#include <type_traits>
#include <gtest/gtest.h>
#include <entt/core/ident.hpp>
struct a_type {};
struct another_type {};
TEST(Ident, Uniqueness) {
using id = entt::ident<a_type, another_type>;
constexpr a_type an_instance;
constexpr another_type another_instance;
ASSERT_NE(id::value<a_type>, id::value<another_type>);
ASSERT_EQ(id::value<a_type>, id::value<decltype(an_instance)>);
ASSERT_NE(id::value<a_type>, id::value<decltype(another_instance)>);
ASSERT_EQ(id::value<a_type>, id::value<a_type>);
ASSERT_EQ(id::value<another_type>, id::value<another_type>);
// test uses in constant expressions
switch(id::value<another_type>) {
case id::value<a_type>:
FAIL();
case id::value<another_type>:
SUCCEED();
}
}
TEST(Identifier, SingleType) {
using id = entt::ident<a_type>;
[[maybe_unused]] std::integral_constant<id::value_type, id::value<a_type>> ic;
}

View File

@ -0,0 +1,55 @@
#include <cstddef>
#include <type_traits>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include <entt/core/iterator.hpp>
struct clazz {
int value{0};
};
TEST(InputIteratorPointer, Functionalities) {
clazz instance{};
entt::input_iterator_pointer ptr{std::move(instance)};
ptr->value = 42;
ASSERT_EQ(instance.value, 0);
ASSERT_EQ(ptr->value, 42);
ASSERT_EQ(ptr->value, (*ptr).value);
ASSERT_EQ(ptr.operator->(), &ptr.operator*());
}
TEST(IotaIterator, Functionalities) {
entt::iota_iterator<std::size_t> first{};
const entt::iota_iterator<std::size_t> last{2u};
ASSERT_NE(first, last);
ASSERT_FALSE(first == last);
ASSERT_TRUE(first != last);
ASSERT_EQ(*first++, 0u);
ASSERT_EQ(*first, 1u);
ASSERT_EQ(*++first, *last);
ASSERT_EQ(*first, 2u);
}
TEST(IterableAdaptor, Functionalities) {
std::vector<int> vec{1, 2};
entt::iterable_adaptor iterable{vec.begin(), vec.end()};
decltype(iterable) other{};
ASSERT_NO_FATAL_FAILURE(other = iterable);
ASSERT_NO_FATAL_FAILURE(std::swap(other, iterable));
ASSERT_EQ(iterable.begin(), vec.begin());
ASSERT_EQ(iterable.end(), vec.end());
ASSERT_EQ(*iterable.cbegin(), 1);
ASSERT_EQ(*++iterable.cbegin(), 2);
ASSERT_EQ(++iterable.cbegin(), --iterable.end());
for(auto value: entt::iterable_adaptor<const int *, const void *>{vec.data(), vec.data() + 1u}) {
ASSERT_EQ(value, 1);
}
}

241
test/entt/core/memory.cpp Normal file
View File

@ -0,0 +1,241 @@
#include <cmath>
#include <cstddef>
#include <limits>
#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include <entt/core/memory.hpp>
#include "../common/basic_test_allocator.hpp"
#include "../common/config.h"
#include "../common/throwing_allocator.hpp"
#include "../common/throwing_type.hpp"
#include "../common/tracked_memory_resource.hpp"
TEST(ToAddress, Functionalities) {
std::shared_ptr<int> shared = std::make_shared<int>();
auto *plain = std::addressof(*shared);
ASSERT_EQ(entt::to_address(shared), plain);
ASSERT_EQ(entt::to_address(plain), plain);
}
TEST(PoccaPocmaAndPocs, Functionalities) {
test::basic_test_allocator<int> lhs, rhs;
// honestly, I don't even know how one is supposed to test such a thing :)
entt::propagate_on_container_copy_assignment(lhs, rhs);
entt::propagate_on_container_move_assignment(lhs, rhs);
entt::propagate_on_container_swap(lhs, rhs);
}
ENTT_DEBUG_TEST(PoccaPocmaAndPocsDeathTest, Functionalities) {
using pocs = std::false_type;
test::basic_test_allocator<int, pocs> lhs, rhs;
ASSERT_DEATH(entt::propagate_on_container_swap(lhs, rhs), "");
}
TEST(IsPowerOfTwo, Functionalities) {
// constexpr-ness guaranteed
constexpr auto zero_is_power_of_two = entt::is_power_of_two(0u);
ASSERT_FALSE(zero_is_power_of_two);
ASSERT_TRUE(entt::is_power_of_two(1u));
ASSERT_TRUE(entt::is_power_of_two(2u));
ASSERT_TRUE(entt::is_power_of_two(4u));
ASSERT_FALSE(entt::is_power_of_two(7u));
ASSERT_TRUE(entt::is_power_of_two(128u));
ASSERT_FALSE(entt::is_power_of_two(200u));
}
TEST(NextPowerOfTwo, Functionalities) {
// constexpr-ness guaranteed
constexpr auto next_power_of_two_of_zero = entt::next_power_of_two(0u);
ASSERT_EQ(next_power_of_two_of_zero, 1u);
ASSERT_EQ(entt::next_power_of_two(1u), 1u);
ASSERT_EQ(entt::next_power_of_two(2u), 2u);
ASSERT_EQ(entt::next_power_of_two(3u), 4u);
ASSERT_EQ(entt::next_power_of_two(17u), 32u);
ASSERT_EQ(entt::next_power_of_two(32u), 32u);
ASSERT_EQ(entt::next_power_of_two(33u), 64u);
ASSERT_EQ(entt::next_power_of_two(std::pow(2, 16)), std::pow(2, 16));
ASSERT_EQ(entt::next_power_of_two(std::pow(2, 16) + 1u), std::pow(2, 17));
}
ENTT_DEBUG_TEST(NextPowerOfTwoDeathTest, Functionalities) {
ASSERT_DEATH(static_cast<void>(entt::next_power_of_two((std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)) + 1)), "");
}
TEST(FastMod, Functionalities) {
// constexpr-ness guaranteed
constexpr auto fast_mod_of_zero = entt::fast_mod(0u, 8u);
ASSERT_EQ(fast_mod_of_zero, 0u);
ASSERT_EQ(entt::fast_mod(7u, 8u), 7u);
ASSERT_EQ(entt::fast_mod(8u, 8u), 0u);
}
TEST(AllocateUnique, Functionalities) {
test::throwing_allocator<test::throwing_type> allocator{};
test::throwing_allocator<test::throwing_type>::trigger_on_allocate = true;
test::throwing_type::trigger_on_value = 0;
ASSERT_THROW((entt::allocate_unique<test::throwing_type>(allocator, 0)), test::throwing_allocator<test::throwing_type>::exception_type);
ASSERT_THROW((entt::allocate_unique<test::throwing_type>(allocator, test::throwing_type{0})), test::throwing_type::exception_type);
std::unique_ptr<test::throwing_type, entt::allocation_deleter<test::throwing_allocator<test::throwing_type>>> ptr = entt::allocate_unique<test::throwing_type>(allocator, 42);
ASSERT_TRUE(ptr);
ASSERT_EQ(*ptr, 42);
ptr.reset();
ASSERT_FALSE(ptr);
}
#if defined(ENTT_HAS_TRACKED_MEMORY_RESOURCE)
TEST(AllocateUnique, NoUsesAllocatorConstruction) {
test::tracked_memory_resource memory_resource{};
std::pmr::polymorphic_allocator<int> allocator{&memory_resource};
using type = std::unique_ptr<int, entt::allocation_deleter<std::pmr::polymorphic_allocator<int>>>;
type ptr = entt::allocate_unique<int>(allocator, 0);
ASSERT_EQ(memory_resource.do_allocate_counter(), 1u);
ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
}
TEST(AllocateUnique, UsesAllocatorConstruction) {
using string_type = typename test::tracked_memory_resource::string_type;
test::tracked_memory_resource memory_resource{};
std::pmr::polymorphic_allocator<string_type> allocator{&memory_resource};
using type = std::unique_ptr<string_type, entt::allocation_deleter<std::pmr::polymorphic_allocator<string_type>>>;
type ptr = entt::allocate_unique<string_type>(allocator, test::tracked_memory_resource::default_value);
ASSERT_GT(memory_resource.do_allocate_counter(), 1u);
ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
}
#endif
TEST(UsesAllocatorConstructionArgs, NoUsesAllocatorConstruction) {
const auto value = 42;
const auto args = entt::uses_allocator_construction_args<int>(std::allocator<int>{}, value);
static_assert(std::tuple_size_v<decltype(args)> == 1u);
static_assert(std::is_same_v<decltype(args), const std::tuple<const int &>>);
ASSERT_EQ(std::get<0>(args), value);
}
TEST(UsesAllocatorConstructionArgs, LeadingAllocatorConvention) {
const auto value = 42;
const auto args = entt::uses_allocator_construction_args<std::tuple<int, char>>(std::allocator<int>{}, value, 'c');
static_assert(std::tuple_size_v<decltype(args)> == 4u);
static_assert(std::is_same_v<decltype(args), const std::tuple<std::allocator_arg_t, const std::allocator<int> &, const int &, char &&>>);
ASSERT_EQ(std::get<2>(args), value);
}
TEST(UsesAllocatorConstructionArgs, TrailingAllocatorConvention) {
const auto size = 42u;
const auto args = entt::uses_allocator_construction_args<std::vector<int>>(std::allocator<int>{}, size);
static_assert(std::tuple_size_v<decltype(args)> == 2u);
static_assert(std::is_same_v<decltype(args), const std::tuple<const unsigned int &, const std::allocator<int> &>>);
ASSERT_EQ(std::get<0>(args), size);
}
TEST(UsesAllocatorConstructionArgs, PairPiecewiseConstruct) {
const auto size = 42u;
const auto tup = std::make_tuple(size);
const auto args = entt::uses_allocator_construction_args<std::pair<int, std::vector<int>>>(std::allocator<int>{}, std::piecewise_construct, std::make_tuple(3), tup);
static_assert(std::tuple_size_v<decltype(args)> == 3u);
static_assert(std::is_same_v<decltype(args), const std::tuple<std::piecewise_construct_t, std::tuple<int &&>, std::tuple<const unsigned int &, const std::allocator<int> &>>>);
ASSERT_EQ(std::get<0>(std::get<2>(args)), size);
}
TEST(UsesAllocatorConstructionArgs, PairNoArgs) {
[[maybe_unused]] const auto args = entt::uses_allocator_construction_args<std::pair<int, std::vector<int>>>(std::allocator<int>{});
static_assert(std::tuple_size_v<decltype(args)> == 3u);
static_assert(std::is_same_v<decltype(args), const std::tuple<std::piecewise_construct_t, std::tuple<>, std::tuple<const std::allocator<int> &>>>);
}
TEST(UsesAllocatorConstructionArgs, PairValues) {
const auto size = 42u;
const auto args = entt::uses_allocator_construction_args<std::pair<int, std::vector<int>>>(std::allocator<int>{}, 3, size);
static_assert(std::tuple_size_v<decltype(args)> == 3u);
static_assert(std::is_same_v<decltype(args), const std::tuple<std::piecewise_construct_t, std::tuple<int &&>, std::tuple<const unsigned int &, const std::allocator<int> &>>>);
ASSERT_EQ(std::get<0>(std::get<2>(args)), size);
}
TEST(UsesAllocatorConstructionArgs, PairConstLValueReference) {
const auto value = std::make_pair(3, 42u);
const auto args = entt::uses_allocator_construction_args<std::pair<int, std::vector<int>>>(std::allocator<int>{}, value);
static_assert(std::tuple_size_v<decltype(args)> == 3u);
static_assert(std::is_same_v<decltype(args), const std::tuple<std::piecewise_construct_t, std::tuple<const int &>, std::tuple<const unsigned int &, const std::allocator<int> &>>>);
ASSERT_EQ(std::get<0>(std::get<1>(args)), 3);
ASSERT_EQ(std::get<0>(std::get<2>(args)), 42u);
}
TEST(UsesAllocatorConstructionArgs, PairRValueReference) {
[[maybe_unused]] const auto args = entt::uses_allocator_construction_args<std::pair<int, std::vector<int>>>(std::allocator<int>{}, std::make_pair(3, 42u));
static_assert(std::tuple_size_v<decltype(args)> == 3u);
static_assert(std::is_same_v<decltype(args), const std::tuple<std::piecewise_construct_t, std::tuple<int &&>, std::tuple<unsigned int &&, const std::allocator<int> &>>>);
}
TEST(MakeObjUsingAllocator, Functionalities) {
const auto size = 42u;
test::throwing_allocator<int>::trigger_on_allocate = true;
ASSERT_THROW((entt::make_obj_using_allocator<std::vector<int, test::throwing_allocator<int>>>(test::throwing_allocator<int>{}, size)), test::throwing_allocator<int>::exception_type);
const auto vec = entt::make_obj_using_allocator<std::vector<int>>(std::allocator<int>{}, size);
ASSERT_FALSE(vec.empty());
ASSERT_EQ(vec.size(), size);
}
TEST(UninitializedConstructUsingAllocator, NoUsesAllocatorConstruction) {
alignas(int) std::byte storage[sizeof(int)];
std::allocator<int> allocator{};
int *value = entt::uninitialized_construct_using_allocator(reinterpret_cast<int *>(&storage), allocator, 42);
ASSERT_EQ(*value, 42);
}
#if defined(ENTT_HAS_TRACKED_MEMORY_RESOURCE)
TEST(UninitializedConstructUsingAllocator, UsesAllocatorConstruction) {
using string_type = typename test::tracked_memory_resource::string_type;
test::tracked_memory_resource memory_resource{};
std::pmr::polymorphic_allocator<string_type> allocator{&memory_resource};
alignas(string_type) std::byte storage[sizeof(string_type)];
string_type *value = entt::uninitialized_construct_using_allocator(reinterpret_cast<string_type *>(&storage), allocator, test::tracked_memory_resource::default_value);
ASSERT_GT(memory_resource.do_allocate_counter(), 0u);
ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
ASSERT_EQ(*value, test::tracked_memory_resource::default_value);
value->~string_type();
}
#endif

View File

@ -0,0 +1,22 @@
#include <gtest/gtest.h>
#include <entt/core/hashed_string.hpp>
#include <entt/core/monostate.hpp>
TEST(Monostate, Functionalities) {
using namespace entt::literals;
const bool b_pre = entt::monostate<entt::hashed_string{"foobar"}>{};
const int i_pre = entt::monostate<"foobar"_hs>{};
ASSERT_FALSE(b_pre);
ASSERT_EQ(i_pre, int{});
entt::monostate<"foobar"_hs>{} = true;
entt::monostate_v<"foobar"_hs> = 42;
const bool &b_post = entt::monostate<"foobar"_hs>{};
const int &i_post = entt::monostate_v<entt::hashed_string{"foobar"}>;
ASSERT_TRUE(b_post);
ASSERT_EQ(i_post, 42);
}

38
test/entt/core/tuple.cpp Normal file
View File

@ -0,0 +1,38 @@
#include <tuple>
#include <gtest/gtest.h>
#include <entt/core/tuple.hpp>
TEST(Tuple, IsTuple) {
static_assert(!entt::is_tuple_v<int>);
static_assert(entt::is_tuple_v<std::tuple<>>);
static_assert(entt::is_tuple_v<std::tuple<int>>);
static_assert(entt::is_tuple_v<std::tuple<int, char>>);
}
TEST(Tuple, UnwrapTuple) {
auto single = std::make_tuple(42);
auto multi = std::make_tuple(42, 'c');
auto ref = std::forward_as_tuple(std::get<0>(single));
ASSERT_TRUE((std::is_same_v<decltype(entt::unwrap_tuple(single)), int &>));
ASSERT_TRUE((std::is_same_v<decltype(entt::unwrap_tuple(multi)), std::tuple<int, char> &>));
ASSERT_TRUE((std::is_same_v<decltype(entt::unwrap_tuple(ref)), int &>));
ASSERT_TRUE((std::is_same_v<decltype(entt::unwrap_tuple(std::move(single))), int &&>));
ASSERT_TRUE((std::is_same_v<decltype(entt::unwrap_tuple(std::move(multi))), std::tuple<int, char> &&>));
ASSERT_TRUE((std::is_same_v<decltype(entt::unwrap_tuple(std::move(ref))), int &>));
ASSERT_TRUE((std::is_same_v<decltype(entt::unwrap_tuple(std::as_const(single))), const int &>));
ASSERT_TRUE((std::is_same_v<decltype(entt::unwrap_tuple(std::as_const(multi))), const std::tuple<int, char> &>));
ASSERT_TRUE((std::is_same_v<decltype(entt::unwrap_tuple(std::as_const(ref))), int &>));
ASSERT_EQ(entt::unwrap_tuple(single), 42);
ASSERT_EQ(entt::unwrap_tuple(multi), multi);
ASSERT_EQ(entt::unwrap_tuple(std::move(ref)), 42);
}
TEST(Tuple, ForwardApply) {
ASSERT_EQ(entt::forward_apply{[](auto &&...args) { return sizeof...(args); }}(std::make_tuple()), 0u);
ASSERT_EQ(entt::forward_apply{[](int i) { return i; }}(std::make_tuple(42)), 42);
ASSERT_EQ(entt::forward_apply{[](auto... args) { return (args + ...); }}(std::make_tuple('a', 1u)), 'b');
}

View File

@ -0,0 +1,116 @@
#include <string_view>
#include <type_traits>
#include <utility>
#include <gtest/gtest.h>
#include <entt/core/type_info.hpp>
#include <entt/core/type_traits.hpp>
template<>
struct entt::type_name<float> final {
[[nodiscard]] static constexpr std::string_view value() noexcept {
return std::string_view{""};
}
};
TEST(TypeIndex, Functionalities) {
ASSERT_EQ(entt::type_index<int>::value(), entt::type_index<int>::value());
ASSERT_NE(entt::type_index<int>::value(), entt::type_index<char>::value());
ASSERT_NE(entt::type_index<int>::value(), entt::type_index<int &&>::value());
ASSERT_NE(entt::type_index<int &>::value(), entt::type_index<const int &>::value());
ASSERT_EQ(static_cast<entt::id_type>(entt::type_index<int>{}), entt::type_index<int>::value());
}
TEST(TypeHash, Functionalities) {
ASSERT_NE(entt::type_hash<int>::value(), entt::type_hash<const int>::value());
ASSERT_NE(entt::type_hash<int>::value(), entt::type_hash<char>::value());
ASSERT_EQ(entt::type_hash<int>::value(), entt::type_hash<int>::value());
ASSERT_EQ(static_cast<entt::id_type>(entt::type_hash<int>{}), entt::type_hash<int>::value());
}
TEST(TypeName, Functionalities) {
ASSERT_EQ(entt::type_name<int>::value(), std::string_view{"int"});
ASSERT_EQ(entt::type_name<float>{}.value(), std::string_view{""});
ASSERT_TRUE((entt::type_name<entt::integral_constant<3>>::value() == std::string_view{"std::integral_constant<int, 3>"})
|| (entt::type_name<entt::integral_constant<3>>::value() == std::string_view{"std::__1::integral_constant<int, 3>"})
|| (entt::type_name<entt::integral_constant<3>>::value() == std::string_view{"struct std::integral_constant<int,3>"}));
ASSERT_TRUE(((entt::type_name<entt::type_list<entt::type_list<int, char>, double>>::value()) == std::string_view{"entt::type_list<entt::type_list<int, char>, double>"})
|| ((entt::type_name<entt::type_list<entt::type_list<int, char>, double>>::value()) == std::string_view{"struct entt::type_list<struct entt::type_list<int,char>,double>"}));
ASSERT_EQ(static_cast<std::string_view>(entt::type_name<int>{}), entt::type_name<int>::value());
}
TEST(TypeInfo, Functionalities) {
static_assert(std::is_copy_constructible_v<entt::type_info>);
static_assert(std::is_move_constructible_v<entt::type_info>);
static_assert(std::is_copy_assignable_v<entt::type_info>);
static_assert(std::is_move_assignable_v<entt::type_info>);
entt::type_info info{std::in_place_type<int>};
entt::type_info other{std::in_place_type<void>};
ASSERT_EQ(info, entt::type_info{std::in_place_type<int &>});
ASSERT_EQ(info, entt::type_info{std::in_place_type<int &&>});
ASSERT_EQ(info, entt::type_info{std::in_place_type<const int &>});
ASSERT_NE(info, other);
ASSERT_TRUE(info == info);
ASSERT_FALSE(info != info);
ASSERT_EQ(info.index(), entt::type_index<int>::value());
ASSERT_EQ(info.hash(), entt::type_hash<int>::value());
ASSERT_EQ(info.name(), entt::type_name<int>::value());
other = info;
ASSERT_EQ(other.index(), entt::type_index<int>::value());
ASSERT_EQ(other.hash(), entt::type_hash<int>::value());
ASSERT_EQ(other.name(), entt::type_name<int>::value());
ASSERT_EQ(other.index(), info.index());
ASSERT_EQ(other.hash(), info.hash());
ASSERT_EQ(other.name(), info.name());
other = std::move(info);
ASSERT_EQ(other.index(), entt::type_index<int>::value());
ASSERT_EQ(other.hash(), entt::type_hash<int>::value());
ASSERT_EQ(other.name(), entt::type_name<int>::value());
ASSERT_EQ(other.index(), info.index());
ASSERT_EQ(other.hash(), info.hash());
ASSERT_EQ(other.name(), info.name());
}
TEST(TypeInfo, Order) {
entt::type_info rhs = entt::type_id<int>();
entt::type_info lhs = entt::type_id<char>();
// let's adjust the two objects since values are generated at runtime
rhs < lhs ? void() : std::swap(lhs, rhs);
ASSERT_FALSE(lhs < lhs);
ASSERT_FALSE(rhs < rhs);
ASSERT_LT(rhs, lhs);
ASSERT_LE(rhs, lhs);
ASSERT_GT(lhs, rhs);
ASSERT_GE(lhs, rhs);
}
TEST(TypeId, Functionalities) {
const int value = 42;
ASSERT_EQ(entt::type_id(value), entt::type_id<int>());
ASSERT_EQ(entt::type_id(42), entt::type_id<int>());
ASSERT_EQ(entt::type_id<int>(), entt::type_id<int>());
ASSERT_EQ(entt::type_id<int &>(), entt::type_id<int &&>());
ASSERT_EQ(entt::type_id<int &>(), entt::type_id<int>());
ASSERT_NE(entt::type_id<int>(), entt::type_id<char>());
ASSERT_EQ(&entt::type_id<int>(), &entt::type_id<int>());
ASSERT_NE(&entt::type_id<int>(), &entt::type_id<void>());
}

View File

@ -0,0 +1,224 @@
#include <functional>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include <entt/core/hashed_string.hpp>
#include <entt/core/type_traits.hpp>
struct not_comparable {
bool operator==(const not_comparable &) const = delete;
};
struct nlohmann_json_like final {
using value_type = nlohmann_json_like;
bool operator==(const nlohmann_json_like &) const {
return true;
}
};
struct clazz {
char foo(int) {
return {};
}
int bar(double, float) const {
return {};
}
bool quux;
};
int free_function(int, const double &) {
return 42;
}
template<typename, typename Type = void>
struct multi_argument_operation {
using type = Type;
};
TEST(SizeOf, Functionalities) {
static_assert(entt::size_of_v<void> == 0u);
static_assert(entt::size_of_v<char> == sizeof(char));
static_assert(entt::size_of_v<int[]> == 0u);
static_assert(entt::size_of_v<int[3]> == sizeof(int[3]));
}
TEST(UnpackAsType, Functionalities) {
auto test = [](auto &&...args) {
return [](entt::unpack_as_type<int, decltype(args)>... value) {
return (value + ... + 0);
};
};
ASSERT_EQ(test('c', 42., true)(1, 2, 3), 6);
}
TEST(UnpackAsValue, Functionalities) {
auto test = [](auto &&...args) {
return (entt::unpack_as_value<2, decltype(args)> + ... + 0);
};
ASSERT_EQ(test('c', 42., true), 6);
}
TEST(IntegralConstant, Functionalities) {
entt::integral_constant<3> constant{};
static_assert(std::is_same_v<typename entt::integral_constant<3>::value_type, int>);
static_assert(constant.value == 3);
}
TEST(Choice, Functionalities) {
static_assert(std::is_base_of_v<entt::choice_t<0>, entt::choice_t<1>>);
static_assert(!std::is_base_of_v<entt::choice_t<1>, entt::choice_t<0>>);
}
TEST(TypeList, Functionalities) {
using type = entt::type_list<int, char>;
using other = entt::type_list<double>;
static_assert(type::size == 2u);
static_assert(other::size == 1u);
static_assert(std::is_same_v<decltype(type{} + other{}), entt::type_list<int, char, double>>);
static_assert(std::is_same_v<entt::type_list_cat_t<type, other, type, other>, entt::type_list<int, char, double, int, char, double>>);
static_assert(std::is_same_v<entt::type_list_cat_t<type, other>, entt::type_list<int, char, double>>);
static_assert(std::is_same_v<entt::type_list_cat_t<type, type>, entt::type_list<int, char, int, char>>);
static_assert(std::is_same_v<entt::type_list_unique_t<entt::type_list_cat_t<type, type>>, entt::type_list<int, char>>);
static_assert(entt::type_list_contains_v<type, int>);
static_assert(entt::type_list_contains_v<type, char>);
static_assert(!entt::type_list_contains_v<type, double>);
static_assert(std::is_same_v<entt::type_list_element_t<0u, type>, int>);
static_assert(std::is_same_v<entt::type_list_element_t<1u, type>, char>);
static_assert(std::is_same_v<entt::type_list_element_t<0u, other>, double>);
static_assert(entt::type_list_index_v<int, type> == 0u);
static_assert(entt::type_list_index_v<char, type> == 1u);
static_assert(entt::type_list_index_v<double, other> == 0u);
static_assert(std::is_same_v<entt::type_list_diff_t<entt::type_list<int, char, double>, entt::type_list<float, bool>>, entt::type_list<int, char, double>>);
static_assert(std::is_same_v<entt::type_list_diff_t<entt::type_list<int, char, double>, entt::type_list<int, char, double>>, entt::type_list<>>);
static_assert(std::is_same_v<entt::type_list_diff_t<entt::type_list<int, char, double>, entt::type_list<int, char>>, entt::type_list<double>>);
static_assert(std::is_same_v<entt::type_list_diff_t<entt::type_list<int, char, double>, entt::type_list<char, double>>, entt::type_list<int>>);
static_assert(std::is_same_v<entt::type_list_diff_t<entt::type_list<int, char, double>, entt::type_list<char>>, entt::type_list<int, double>>);
static_assert(std::is_same_v<entt::type_list_transform_t<entt::type_list<int, char>, entt::type_identity>, entt::type_list<int, char>>);
static_assert(std::is_same_v<entt::type_list_transform_t<entt::type_list<int, char>, std::add_const>, entt::type_list<const int, const char>>);
static_assert(std::is_same_v<entt::type_list_transform_t<entt::type_list<int, char>, multi_argument_operation>, entt::type_list<void, void>>);
}
TEST(ValueList, Functionalities) {
using value = entt::value_list<0, 2>;
using other = entt::value_list<1>;
static_assert(value::size == 2u);
static_assert(other::size == 1u);
static_assert(std::is_same_v<decltype(value{} + other{}), entt::value_list<0, 2, 1>>);
static_assert(std::is_same_v<entt::value_list_cat_t<value, other, value, other>, entt::value_list<0, 2, 1, 0, 2, 1>>);
static_assert(std::is_same_v<entt::value_list_cat_t<value, other>, entt::value_list<0, 2, 1>>);
static_assert(std::is_same_v<entt::value_list_cat_t<value, value>, entt::value_list<0, 2, 0, 2>>);
static_assert(entt::value_list_element_v<0u, value> == 0);
static_assert(entt::value_list_element_v<1u, value> == 2);
static_assert(entt::value_list_element_v<0u, other> == 1);
}
TEST(IsApplicable, Functionalities) {
static_assert(entt::is_applicable_v<void(int, char), std::tuple<double, char>>);
static_assert(!entt::is_applicable_v<void(int, char), std::tuple<int>>);
static_assert(entt::is_applicable_r_v<float, int(int, char), std::tuple<double, char>>);
static_assert(!entt::is_applicable_r_v<float, void(int, char), std::tuple<double, char>>);
static_assert(!entt::is_applicable_r_v<int, int(int, char), std::tuple<void>>);
}
TEST(IsComplete, Functionalities) {
static_assert(!entt::is_complete_v<void>);
static_assert(entt::is_complete_v<int>);
}
TEST(IsIterator, Functionalities) {
static_assert(!entt::is_iterator_v<void>);
static_assert(!entt::is_iterator_v<int>);
static_assert(!entt::is_iterator_v<void *>);
static_assert(entt::is_iterator_v<int *>);
static_assert(entt::is_iterator_v<std::vector<int>::iterator>);
static_assert(entt::is_iterator_v<std::vector<int>::const_iterator>);
static_assert(entt::is_iterator_v<std::vector<int>::reverse_iterator>);
}
TEST(IsEBCOEligible, Functionalities) {
static_assert(entt::is_ebco_eligible_v<not_comparable>);
static_assert(!entt::is_ebco_eligible_v<nlohmann_json_like>);
static_assert(!entt::is_ebco_eligible_v<double>);
static_assert(!entt::is_ebco_eligible_v<void>);
}
TEST(IsTransparent, Functionalities) {
static_assert(!entt::is_transparent_v<std::less<int>>);
static_assert(entt::is_transparent_v<std::less<void>>);
static_assert(!entt::is_transparent_v<std::logical_not<double>>);
static_assert(entt::is_transparent_v<std::logical_not<void>>);
}
TEST(IsEqualityComparable, Functionalities) {
static_assert(entt::is_equality_comparable_v<int>);
static_assert(entt::is_equality_comparable_v<const int>);
static_assert(entt::is_equality_comparable_v<std::vector<int>>);
static_assert(entt::is_equality_comparable_v<std::vector<std::vector<int>>>);
static_assert(entt::is_equality_comparable_v<std::unordered_map<int, int>>);
static_assert(entt::is_equality_comparable_v<std::unordered_map<int, std::unordered_map<int, char>>>);
static_assert(entt::is_equality_comparable_v<std::pair<const int, int>>);
static_assert(entt::is_equality_comparable_v<std::pair<const int, std::unordered_map<int, char>>>);
static_assert(entt::is_equality_comparable_v<std::vector<not_comparable>::iterator>);
static_assert(entt::is_equality_comparable_v<nlohmann_json_like>);
static_assert(!entt::is_equality_comparable_v<not_comparable>);
static_assert(!entt::is_equality_comparable_v<const not_comparable>);
static_assert(!entt::is_equality_comparable_v<std::vector<not_comparable>>);
static_assert(!entt::is_equality_comparable_v<std::vector<std::vector<not_comparable>>>);
static_assert(!entt::is_equality_comparable_v<std::unordered_map<int, not_comparable>>);
static_assert(!entt::is_equality_comparable_v<std::unordered_map<int, std::unordered_map<int, not_comparable>>>);
static_assert(!entt::is_equality_comparable_v<std::pair<const int, not_comparable>>);
static_assert(!entt::is_equality_comparable_v<std::pair<const int, std::unordered_map<int, not_comparable>>>);
static_assert(!entt::is_equality_comparable_v<void>);
}
TEST(ConstnessAs, Functionalities) {
static_assert(std::is_same_v<entt::constness_as_t<int, char>, int>);
static_assert(std::is_same_v<entt::constness_as_t<const int, char>, int>);
static_assert(std::is_same_v<entt::constness_as_t<int, const char>, const int>);
static_assert(std::is_same_v<entt::constness_as_t<const int, const char>, const int>);
}
TEST(MemberClass, Functionalities) {
static_assert(std::is_same_v<clazz, entt::member_class_t<decltype(&clazz::foo)>>);
static_assert(std::is_same_v<clazz, entt::member_class_t<decltype(&clazz::bar)>>);
static_assert(std::is_same_v<clazz, entt::member_class_t<decltype(&clazz::quux)>>);
}
TEST(NthArgument, Functionalities) {
static_assert(std::is_same_v<entt::nth_argument_t<0u, &free_function>, int>);
static_assert(std::is_same_v<entt::nth_argument_t<1u, &free_function>, const double &>);
static_assert(std::is_same_v<entt::nth_argument_t<0u, &clazz::bar>, double>);
static_assert(std::is_same_v<entt::nth_argument_t<1u, &clazz::bar>, float>);
static_assert(std::is_same_v<entt::nth_argument_t<0u, &clazz::quux>, bool>);
ASSERT_EQ(free_function(entt::nth_argument_t<0u, &free_function>{}, entt::nth_argument_t<1u, &free_function>{}), 42);
}
TEST(Tag, Functionalities) {
using namespace entt::literals;
static_assert(entt::tag<"foobar"_hs>::value == entt::hashed_string::value("foobar"));
static_assert(std::is_same_v<typename entt::tag<"foobar"_hs>::value_type, entt::id_type>);
}

View File

@ -0,0 +1,61 @@
#include <utility>
#include <gtest/gtest.h>
#include <entt/core/type_traits.hpp>
#include <entt/core/utility.hpp>
struct functions {
static void foo(int) {}
static void foo() {}
void bar(int) {}
void bar() {}
};
TEST(Identity, Functionalities) {
entt::identity identity;
int value = 42;
ASSERT_TRUE(entt::is_transparent_v<entt::identity>);
ASSERT_EQ(identity(value), value);
ASSERT_EQ(&identity(value), &value);
}
TEST(Overload, Functionalities) {
ASSERT_EQ(entt::overload<void(int)>(&functions::foo), static_cast<void (*)(int)>(&functions::foo));
ASSERT_EQ(entt::overload<void()>(&functions::foo), static_cast<void (*)()>(&functions::foo));
ASSERT_EQ(entt::overload<void(int)>(&functions::bar), static_cast<void (functions::*)(int)>(&functions::bar));
ASSERT_EQ(entt::overload<void()>(&functions::bar), static_cast<void (functions::*)()>(&functions::bar));
functions instance;
ASSERT_NO_FATAL_FAILURE(entt::overload<void(int)>(&functions::foo)(0));
ASSERT_NO_FATAL_FAILURE(entt::overload<void()>(&functions::foo)());
ASSERT_NO_FATAL_FAILURE((instance.*entt::overload<void(int)>(&functions::bar))(0));
ASSERT_NO_FATAL_FAILURE((instance.*entt::overload<void()>(&functions::bar))());
}
TEST(Overloaded, Functionalities) {
int iv = 0;
char cv = '\0';
entt::overloaded func{
[&iv](int value) { iv = value; },
[&cv](char value) { cv = value; }};
func(42);
func('c');
ASSERT_EQ(iv, 42);
ASSERT_EQ(cv, 'c');
}
TEST(YCombinator, Functionalities) {
entt::y_combinator gauss([](const auto &self, auto value) -> unsigned int {
return value ? (value + self(value - 1u)) : 0;
});
ASSERT_EQ(gauss(3u), 3u * 4u / 2u);
ASSERT_EQ(std::as_const(gauss)(7u), 7u * 8u / 2u);
}