mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Status (for both STL and Non-STL builds): - Builds and tests with GCC 16 - Clang 22: Reflection not available yet - MSVC: Reflection not available yet
2392 lines
94 KiB
C++
2392 lines
94 KiB
C++
/******************************************************************************
|
|
The MIT License(MIT)
|
|
|
|
Embedded Template Library.
|
|
https://github.com/ETLCPP/etl
|
|
https://www.etlcpp.com
|
|
|
|
Copyright(c) 2026 BMW AG
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files(the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions :
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
******************************************************************************/
|
|
|
|
#include "unit_test_framework.h"
|
|
|
|
#include "etl/meta.h"
|
|
|
|
#if ETL_HAS_REFLECTION
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Helper macros: evaluate consteval-only expressions at compile time,
|
|
// then pass the plain bool/value result to the runtime CHECK framework.
|
|
// GCC 16's std::meta::info is a consteval-only type and cannot appear
|
|
// in runtime expressions such as those generated by CHECK().
|
|
//---------------------------------------------------------------------------
|
|
#define CONSTEXPR_CHECK(expr) \
|
|
do { \
|
|
constexpr bool _etl_chk_ = (expr); \
|
|
CHECK(_etl_chk_); \
|
|
} while (0)
|
|
|
|
#define CONSTEXPR_CHECK_FALSE(expr) \
|
|
do { \
|
|
constexpr bool _etl_chk_ = (expr); \
|
|
CHECK(!_etl_chk_); \
|
|
} while (0)
|
|
|
|
#define CONSTEXPR_CHECK_EQUAL(expected, expr) \
|
|
do { \
|
|
constexpr auto _etl_val_ = (expr); \
|
|
CHECK_EQUAL(expected, _etl_val_); \
|
|
} while (0)
|
|
|
|
//---------------------------------------------------------------------------
|
|
// In an STL build identifier_of / symbol_of return std::string_view.
|
|
// In the non-STL build they return etl::string_view.
|
|
// Use this alias so the test code is compatible with both.
|
|
//---------------------------------------------------------------------------
|
|
#if ETL_USING_STL
|
|
using meta_string_view = std::string_view;
|
|
#else
|
|
using meta_string_view = etl::string_view;
|
|
#endif
|
|
|
|
// A struct with external linkage (defined outside anonymous namespace).
|
|
struct ExternalLinkageStruct
|
|
{
|
|
int val;
|
|
};
|
|
|
|
namespace
|
|
{
|
|
//---------------------------------------------------------------------------
|
|
// Simple aggregate with public fields (naming, member queries, layout).
|
|
//---------------------------------------------------------------------------
|
|
struct SimpleStruct
|
|
{
|
|
int x;
|
|
double y;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// A union type (is_union_type).
|
|
//---------------------------------------------------------------------------
|
|
union TestUnion
|
|
{
|
|
int i;
|
|
float f;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Struct with mixed access (access predicates, inaccessible-member queries).
|
|
//---------------------------------------------------------------------------
|
|
struct MixedAccess
|
|
{
|
|
public:
|
|
|
|
int pub;
|
|
|
|
protected:
|
|
|
|
int prot;
|
|
|
|
private:
|
|
|
|
[[maybe_unused]]
|
|
int priv;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Struct with a mutable member, a const member, and a volatile member.
|
|
//---------------------------------------------------------------------------
|
|
struct CVQualifiedMembers
|
|
{
|
|
mutable int m;
|
|
const int c = 0;
|
|
volatile int v;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Bit-field struct (is_bit_field, bit_size_of, bit_offset_of).
|
|
//---------------------------------------------------------------------------
|
|
struct BitFields
|
|
{
|
|
unsigned a : 3;
|
|
unsigned b : 5;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Scoped and unscoped enumerations (enumerators_of, is_scoped_enum_type).
|
|
//---------------------------------------------------------------------------
|
|
enum class Color
|
|
{
|
|
Red,
|
|
Green,
|
|
Blue
|
|
};
|
|
enum Direction
|
|
{
|
|
North,
|
|
South,
|
|
East,
|
|
West
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Base / Derived hierarchy (bases_of, is_base, is_virtual, is_override).
|
|
//---------------------------------------------------------------------------
|
|
struct Base
|
|
{
|
|
virtual ~Base() = default;
|
|
virtual void vfunc() {}
|
|
int base_data = 0;
|
|
};
|
|
|
|
struct Derived : public Base
|
|
{
|
|
void vfunc() override {}
|
|
int derived_data = 0;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Class with a pure-virtual function (is_pure_virtual, is_abstract_type).
|
|
//---------------------------------------------------------------------------
|
|
struct AbstractBase
|
|
{
|
|
virtual ~AbstractBase() = default;
|
|
virtual void pure() = 0;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Final class (is_final, is_final_type).
|
|
//---------------------------------------------------------------------------
|
|
struct FinalClass final : Derived
|
|
{
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Class with explicit / deleted / defaulted / noexcept special members.
|
|
//---------------------------------------------------------------------------
|
|
struct SpecialMembers
|
|
{
|
|
SpecialMembers() = default;
|
|
SpecialMembers(const SpecialMembers&) = delete;
|
|
SpecialMembers(SpecialMembers&&) noexcept = default;
|
|
SpecialMembers& operator=(const SpecialMembers&) = default;
|
|
SpecialMembers& operator=(SpecialMembers&&) noexcept = default;
|
|
~SpecialMembers() = default;
|
|
|
|
explicit SpecialMembers(int) {}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Class with operator overloads (operator_of, symbol_of, is_operator_function).
|
|
//---------------------------------------------------------------------------
|
|
struct Operators
|
|
{
|
|
bool operator==(const Operators&) const = default;
|
|
Operators operator+(const Operators&) const
|
|
{
|
|
return {};
|
|
}
|
|
int operator()(int a) const
|
|
{
|
|
return a;
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Class with a static data member (static_data_members_of, has_static_storage_duration).
|
|
//---------------------------------------------------------------------------
|
|
struct WithStatic
|
|
{
|
|
[[maybe_unused]]
|
|
static inline int s_count = 0;
|
|
int value = 0;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Type alias (is_type_alias, dealias).
|
|
//---------------------------------------------------------------------------
|
|
using IntAlias = int;
|
|
|
|
//---------------------------------------------------------------------------
|
|
// A simple class template (is_class_template, template_of, template_arguments_of, substitute).
|
|
//---------------------------------------------------------------------------
|
|
template <typename T, size_t N>
|
|
struct FixedArray
|
|
{
|
|
T data[N];
|
|
};
|
|
|
|
using IntArray5 = FixedArray<int, 5>;
|
|
|
|
//---------------------------------------------------------------------------
|
|
// A constexpr function (reflect_function) and a constexpr variable (reflect_object).
|
|
//---------------------------------------------------------------------------
|
|
constexpr int global_const = 42;
|
|
|
|
constexpr int add(int a, int b)
|
|
{
|
|
return a + b;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// A function with default arguments and variadic-style overload (parameter reflection).
|
|
//---------------------------------------------------------------------------
|
|
[[maybe_unused]]
|
|
int with_default(int a, int b = 10)
|
|
{
|
|
return a + b;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// An empty struct (is_empty_type, is_aggregate_type).
|
|
//---------------------------------------------------------------------------
|
|
struct Empty
|
|
{
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// A polymorphic non-abstract class (is_polymorphic_type but not is_abstract_type).
|
|
//---------------------------------------------------------------------------
|
|
struct Polymorphic
|
|
{
|
|
virtual ~Polymorphic() = default;
|
|
virtual void foo() {}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// A trivially-copyable, non-polymorphic POD-like struct.
|
|
//---------------------------------------------------------------------------
|
|
struct Trivial
|
|
{
|
|
int a;
|
|
int b;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Class with ref-qualified member functions (is_lvalue/rvalue_reference_qualified).
|
|
//---------------------------------------------------------------------------
|
|
struct RefQualified
|
|
{
|
|
void lref() & {}
|
|
void rref() && {}
|
|
void none() {}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Class with a conversion operator (is_conversion_function).
|
|
//---------------------------------------------------------------------------
|
|
struct WithConversion
|
|
{
|
|
operator int() const
|
|
{
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Class with a deducing-this (explicit object parameter) member.
|
|
//---------------------------------------------------------------------------
|
|
struct WithDeducingThis
|
|
{
|
|
int value = 0;
|
|
int get(this WithDeducingThis const& self)
|
|
{
|
|
return self.value;
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// A thread_local variable (has_thread_storage_duration).
|
|
//---------------------------------------------------------------------------
|
|
[[maybe_unused]]
|
|
thread_local int tls_var = 0;
|
|
|
|
//---------------------------------------------------------------------------
|
|
// A constexpr helper for is_structural_type — structural types can be used
|
|
// as non-type template parameters.
|
|
//---------------------------------------------------------------------------
|
|
struct Structural
|
|
{
|
|
int x;
|
|
// Structural: all members public, no virtual, no user-declared ctors.
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// A namespace-level variable with internal linkage.
|
|
//---------------------------------------------------------------------------
|
|
[[maybe_unused]]
|
|
static int internal_var = 0;
|
|
|
|
SUITE(test_meta)
|
|
{
|
|
//=========================================================================
|
|
// Naming / identification
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_identifier_of_type)
|
|
{
|
|
// identifier_of on a reflected type should return its unqualified name.
|
|
constexpr auto name = etl::meta::identifier_of(^^SimpleStruct);
|
|
CONSTEXPR_CHECK(name == "SimpleStruct");
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_identifier_of_member)
|
|
{
|
|
// identifier_of on a reflected data member should return the field name.
|
|
constexpr auto name_x =
|
|
etl::meta::identifier_of(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[0]);
|
|
constexpr auto name_y =
|
|
etl::meta::identifier_of(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[1]);
|
|
CHECK(meta_string_view("x") == name_x);
|
|
CHECK(meta_string_view("y") == name_y);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_identifier_of_enum_type)
|
|
{
|
|
// identifier_of on a reflected enumeration type.
|
|
constexpr auto name = etl::meta::identifier_of(^^Color);
|
|
CONSTEXPR_CHECK(name == "Color");
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_identifier_of_enumerator)
|
|
{
|
|
// identifier_of on individual enumerators.
|
|
CONSTEXPR_CHECK(meta_string_view("Red") == etl::meta::identifier_of(etl::meta::enumerators_of(^^Color)[0]));
|
|
CONSTEXPR_CHECK(meta_string_view("Green") == etl::meta::identifier_of(etl::meta::enumerators_of(^^Color)[1]));
|
|
CONSTEXPR_CHECK(meta_string_view("Blue") == etl::meta::identifier_of(etl::meta::enumerators_of(^^Color)[2]));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_identifier)
|
|
{
|
|
// Named entities have identifiers; built-in types may not.
|
|
CONSTEXPR_CHECK(etl::meta::has_identifier(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::has_identifier(^^Color));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_operator_of_and_symbol_of)
|
|
{
|
|
// Find operator== in Operators and verify operator_of / symbol_of.
|
|
// Locate the operator== member.
|
|
constexpr auto it = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^Operators, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
{
|
|
if (etl::meta::is_operator_function(m) && etl::meta::operator_of(m) == etl::meta::op_equals_equals)
|
|
return m;
|
|
}
|
|
return etl::meta::info{};
|
|
}();
|
|
|
|
CONSTEXPR_CHECK(it != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::operator_of(it) == etl::meta::op_equals_equals);
|
|
CONSTEXPR_CHECK(meta_string_view("==") == etl::meta::symbol_of(etl::meta::op_equals_equals));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_symbol_of_various_operators)
|
|
{
|
|
// Spot-check symbol_of for a few operator enumerators.
|
|
CONSTEXPR_CHECK(etl::meta::symbol_of(etl::meta::op_plus) == "+");
|
|
CONSTEXPR_CHECK(etl::meta::symbol_of(etl::meta::op_minus) == "-");
|
|
CONSTEXPR_CHECK(etl::meta::symbol_of(etl::meta::op_parentheses) == "()");
|
|
CONSTEXPR_CHECK(etl::meta::symbol_of(etl::meta::op_spaceship) == "<=>");
|
|
CONSTEXPR_CHECK(etl::meta::symbol_of(etl::meta::op_square_brackets) == "[]");
|
|
}
|
|
|
|
//=========================================================================
|
|
// Core entity queries
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_type_of_data_member)
|
|
{
|
|
// type_of on the first member of SimpleStruct should reflect int.
|
|
constexpr auto t = etl::meta::type_of(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[0]);
|
|
CONSTEXPR_CHECK(t == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_type_of_second_member)
|
|
{
|
|
// type_of on the second member of SimpleStruct should reflect double.
|
|
constexpr auto t = etl::meta::type_of(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[1]);
|
|
CONSTEXPR_CHECK(t == ^^double);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_parent_of_data_member)
|
|
{
|
|
// parent_of a data member should be the containing class.
|
|
constexpr auto parent = etl::meta::parent_of(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[0]);
|
|
CONSTEXPR_CHECK(parent == ^^SimpleStruct);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_dealias)
|
|
{
|
|
// dealias on a type alias should yield the underlying type.
|
|
constexpr auto dealiased = etl::meta::dealias(^^IntAlias);
|
|
CONSTEXPR_CHECK(dealiased == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_constant_of)
|
|
{
|
|
// constant_of on a reflected constexpr variable should yield a value reflection.
|
|
constexpr auto val = etl::meta::extract<int>(etl::meta::constant_of(^^global_const));
|
|
CHECK_EQUAL(42, val);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_template_of)
|
|
{
|
|
// template_of on an instantiation should return the primary template.
|
|
// IntArray5 is a type alias, so dealias first to get the instantiation.
|
|
constexpr auto tmpl = etl::meta::template_of(etl::meta::dealias(^^IntArray5));
|
|
CONSTEXPR_CHECK(tmpl == ^^FixedArray);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_template_arguments_of)
|
|
{
|
|
// template_arguments_of on FixedArray<int, 5> should give two arguments.
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto args = etl::meta::template_arguments_of(etl::meta::dealias(^^IntArray5));
|
|
struct R
|
|
{
|
|
size_t sz;
|
|
bool arg0_is_int;
|
|
size_t arg1;
|
|
};
|
|
return R{args.size(), args[0] == ^^int, etl::meta::extract<size_t>(args[1])};
|
|
}();
|
|
CHECK_EQUAL(size_t(2), result.sz);
|
|
// First argument is the type int.
|
|
CONSTEXPR_CHECK(result.arg0_is_int);
|
|
// Second argument is the value 5.
|
|
CHECK_EQUAL(size_t(5), result.arg1);
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4a: Access specifier predicates
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_public)
|
|
{
|
|
// The first nonstatic data member of MixedAccess (pub) is public.
|
|
constexpr auto m0 = etl::meta::nonstatic_data_members_of(^^MixedAccess, etl::meta::access_context::unchecked())[0];
|
|
CONSTEXPR_CHECK(etl::meta::is_public(m0));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_protected(m0));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_private(m0));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_protected)
|
|
{
|
|
// The second nonstatic data member of MixedAccess (prot) is protected.
|
|
constexpr auto m1 = etl::meta::nonstatic_data_members_of(^^MixedAccess, etl::meta::access_context::unchecked())[1];
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_public(m1));
|
|
CONSTEXPR_CHECK(etl::meta::is_protected(m1));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_private(m1));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_private)
|
|
{
|
|
// The third nonstatic data member of MixedAccess (priv) is private.
|
|
constexpr auto m2 = etl::meta::nonstatic_data_members_of(^^MixedAccess, etl::meta::access_context::unchecked())[2];
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_public(m2));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_protected(m2));
|
|
CONSTEXPR_CHECK(etl::meta::is_private(m2));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4b: Virtual / override predicates
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_virtual)
|
|
{
|
|
// Base::vfunc is virtual.
|
|
constexpr auto vfunc = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^Base, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::has_identifier(m) && etl::meta::identifier_of(m) == "vfunc")
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(vfunc != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_virtual(vfunc));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_pure_virtual)
|
|
{
|
|
// AbstractBase::pure is pure-virtual.
|
|
constexpr auto pure_fn = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^AbstractBase, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::has_identifier(m) && etl::meta::identifier_of(m) == "pure")
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(pure_fn != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_pure_virtual(pure_fn));
|
|
CONSTEXPR_CHECK(etl::meta::is_virtual(pure_fn));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_override)
|
|
{
|
|
// Derived::vfunc is an override.
|
|
constexpr auto vfunc = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^Derived, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::has_identifier(m) && etl::meta::identifier_of(m) == "vfunc")
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(vfunc != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_override(vfunc));
|
|
CONSTEXPR_CHECK(etl::meta::is_virtual(vfunc));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_non_virtual_member_is_not_virtual)
|
|
{
|
|
// Base::base_data is not virtual.
|
|
// base_data is a data member, so is_virtual should be false.
|
|
constexpr auto base_data = []() consteval
|
|
{
|
|
auto members = etl::meta::nonstatic_data_members_of(^^Base, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::identifier_of(m) == "base_data")
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(base_data != etl::meta::info{});
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_virtual(base_data));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4c: Function property predicates
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_defaulted)
|
|
{
|
|
// SpecialMembers default constructor is defaulted.
|
|
constexpr auto def_ctor = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_default_constructor(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(def_ctor != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_defaulted(def_ctor));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_deleted)
|
|
{
|
|
// SpecialMembers copy constructor is deleted.
|
|
constexpr auto copy_ctor = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_copy_constructor(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(copy_ctor != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_deleted(copy_ctor));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_explicit)
|
|
{
|
|
// SpecialMembers(int) is explicit.
|
|
constexpr auto int_ctor = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_constructor(m) && !etl::meta::is_default_constructor(m) && !etl::meta::is_copy_constructor(m)
|
|
&& !etl::meta::is_move_constructor(m) && etl::meta::is_explicit(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(int_ctor != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_explicit(int_ctor));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_noexcept)
|
|
{
|
|
// SpecialMembers move constructor is noexcept.
|
|
constexpr auto move_ctor = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_move_constructor(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(move_ctor != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_noexcept(move_ctor));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4d: Data member / misc predicates
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_bit_field)
|
|
{
|
|
// BitFields::a and ::b are bit-fields.
|
|
CONSTEXPR_CHECK(etl::meta::is_bit_field(etl::meta::nonstatic_data_members_of(^^BitFields, etl::meta::access_context::unchecked())[0]));
|
|
CONSTEXPR_CHECK(etl::meta::is_bit_field(etl::meta::nonstatic_data_members_of(^^BitFields, etl::meta::access_context::unchecked())[1]));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_non_bitfield_is_not_bit_field)
|
|
{
|
|
// SimpleStruct::x is not a bit-field.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_bit_field(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[0]));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_enumerator)
|
|
{
|
|
// Each element of enumerators_of(^^Color) should satisfy is_enumerator.
|
|
constexpr bool all_enumerators = []() consteval
|
|
{
|
|
auto enums = etl::meta::enumerators_of(^^Color);
|
|
for (auto e : enums)
|
|
if (!etl::meta::is_enumerator(e))
|
|
return false;
|
|
return true;
|
|
}();
|
|
CHECK(all_enumerators);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_non_enumerator_is_not_enumerator)
|
|
{
|
|
// A data member is not an enumerator.
|
|
CONSTEXPR_CHECK_FALSE(
|
|
etl::meta::is_enumerator(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[0]));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_final)
|
|
{
|
|
// FinalClass is final.
|
|
CONSTEXPR_CHECK(etl::meta::is_final(^^FinalClass));
|
|
// Base is not final.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_final(^^Base));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4e: CV / ref qualification predicates
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_mutable_member)
|
|
{
|
|
// CVQualifiedMembers::m is mutable.
|
|
// members[0] = m (mutable), members[1] = c (const), members[2] = v (volatile)
|
|
constexpr auto m0 = etl::meta::nonstatic_data_members_of(^^CVQualifiedMembers, etl::meta::access_context::unchecked())[0];
|
|
constexpr auto m1 = etl::meta::nonstatic_data_members_of(^^CVQualifiedMembers, etl::meta::access_context::unchecked())[1];
|
|
constexpr auto m2 = etl::meta::nonstatic_data_members_of(^^CVQualifiedMembers, etl::meta::access_context::unchecked())[2];
|
|
CONSTEXPR_CHECK(etl::meta::is_mutable_member(m0));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_mutable_member(m1));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_mutable_member(m2));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_const_on_type)
|
|
{
|
|
// is_const on ^^const int should be true.
|
|
CONSTEXPR_CHECK(etl::meta::is_const(^^const int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_const(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_volatile_on_type)
|
|
{
|
|
// is_volatile on ^^volatile int should be true.
|
|
CONSTEXPR_CHECK(etl::meta::is_volatile(^^volatile int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_volatile(^^int));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4f: Storage duration & linkage
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_static_storage_duration)
|
|
{
|
|
// WithStatic::s_count has static storage duration.
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto statics = etl::meta::static_data_members_of(^^WithStatic, etl::meta::access_context::unchecked());
|
|
struct R
|
|
{
|
|
size_t sz;
|
|
bool has_static;
|
|
};
|
|
return R{statics.size(), statics.size() >= 1 && etl::meta::has_static_storage_duration(statics[0])};
|
|
}();
|
|
CHECK(result.sz >= size_t(1));
|
|
CHECK(result.has_static);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_internal_linkage)
|
|
{
|
|
// internal_var (declared static at namespace scope) has internal linkage.
|
|
CONSTEXPR_CHECK(etl::meta::has_internal_linkage(^^internal_var));
|
|
CONSTEXPR_CHECK(etl::meta::has_linkage(^^internal_var));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_external_linkage)
|
|
{
|
|
// ExternalLinkageStruct is defined outside anonymous namespace
|
|
// so it has external linkage.
|
|
CONSTEXPR_CHECK(etl::meta::has_external_linkage(^^ExternalLinkageStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_linkage)
|
|
{
|
|
// Types and namespace-scope variables have linkage.
|
|
CONSTEXPR_CHECK(etl::meta::has_linkage(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::has_linkage(^^internal_var));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4g: Membership predicates
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_class_member)
|
|
{
|
|
// SimpleStruct::x is a class member.
|
|
CONSTEXPR_CHECK(etl::meta::is_class_member(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[0]));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_namespace_member)
|
|
{
|
|
// global_const is a namespace member (it lives at namespace scope).
|
|
CONSTEXPR_CHECK(etl::meta::is_namespace_member(^^global_const));
|
|
// A data member is not a namespace member.
|
|
CONSTEXPR_CHECK_FALSE(
|
|
etl::meta::is_namespace_member(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[0]));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_nonstatic_data_member)
|
|
{
|
|
// SimpleStruct::x is a non-static data member.
|
|
CONSTEXPR_CHECK(
|
|
etl::meta::is_nonstatic_data_member(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[0]));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_static_member)
|
|
{
|
|
// WithStatic::s_count is a static member.
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto statics = etl::meta::static_data_members_of(^^WithStatic, etl::meta::access_context::unchecked());
|
|
struct R
|
|
{
|
|
size_t sz;
|
|
bool is_static;
|
|
};
|
|
return R{statics.size(), statics.size() >= 1 && etl::meta::is_static_member(statics[0])};
|
|
}();
|
|
CHECK(result.sz >= size_t(1));
|
|
CHECK(result.is_static);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_base)
|
|
{
|
|
// The base-class specifier in Derived should satisfy is_base.
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto bases = etl::meta::bases_of(^^Derived, etl::meta::access_context::unchecked());
|
|
struct R
|
|
{
|
|
size_t sz;
|
|
bool is_base_val;
|
|
};
|
|
return R{bases.size(), bases.size() == 1 && etl::meta::is_base(bases[0])};
|
|
}();
|
|
CHECK_EQUAL(size_t(1), result.sz);
|
|
CHECK(result.is_base_val);
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4h: Entity kind predicates
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_type(^^int));
|
|
CONSTEXPR_CHECK(etl::meta::is_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_type(^^Color));
|
|
// A variable is not a type.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_type(^^global_const));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_namespace)
|
|
{
|
|
// The global namespace is a namespace.
|
|
CONSTEXPR_CHECK(etl::meta::is_namespace(^^::));
|
|
// A type is not a namespace.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_namespace(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_function)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_function(^^add));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_function(^^global_const));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_function(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_variable)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_variable(^^global_const));
|
|
CONSTEXPR_CHECK(etl::meta::is_variable(^^internal_var));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_variable(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_type_alias)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_type_alias(^^IntAlias));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_type_alias(^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_type_alias(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_complete_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_complete_type(^^int));
|
|
CONSTEXPR_CHECK(etl::meta::is_complete_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_complete_type(^^Color));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_enumerable_type)
|
|
{
|
|
// Enums with a definition are enumerable.
|
|
CONSTEXPR_CHECK(etl::meta::is_enumerable_type(^^Color));
|
|
CONSTEXPR_CHECK(etl::meta::is_enumerable_type(^^Direction));
|
|
// A non-enum, non-class scalar is not enumerable.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_enumerable_type(^^int));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4i: Template predicates
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_template)
|
|
{
|
|
// FixedArray is a template; its instantiation (dealiased IntArray5) is not.
|
|
CONSTEXPR_CHECK(etl::meta::is_template(^^FixedArray));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_template(etl::meta::dealias(^^IntArray5)));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_class_template)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_class_template(^^FixedArray));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_class_template(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_template_arguments)
|
|
{
|
|
// An instantiation has template arguments; the primary template does not.
|
|
// IntArray5 is a type alias, so dealias to get the instantiation.
|
|
CONSTEXPR_CHECK(etl::meta::has_template_arguments(etl::meta::dealias(^^IntArray5)));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::has_template_arguments(^^SimpleStruct));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4j: Special member function predicates
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_constructor)
|
|
{
|
|
// SpecialMembers has constructors; find at least one.
|
|
constexpr bool found = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_constructor(m))
|
|
return true;
|
|
return false;
|
|
}();
|
|
CHECK(found);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_default_constructor)
|
|
{
|
|
constexpr auto def_ctor = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_default_constructor(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(def_ctor != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_special_member_function(def_ctor));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_copy_constructor)
|
|
{
|
|
constexpr auto copy_ctor = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_copy_constructor(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(copy_ctor != etl::meta::info{});
|
|
// This one is deleted.
|
|
CONSTEXPR_CHECK(etl::meta::is_deleted(copy_ctor));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_move_constructor)
|
|
{
|
|
constexpr auto move_ctor = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_move_constructor(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(move_ctor != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_noexcept(move_ctor));
|
|
CONSTEXPR_CHECK(etl::meta::is_defaulted(move_ctor));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_destructor)
|
|
{
|
|
constexpr auto dtor = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_destructor(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(dtor != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_special_member_function(dtor));
|
|
CONSTEXPR_CHECK(etl::meta::is_defaulted(dtor));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_copy_assignment)
|
|
{
|
|
constexpr auto copy_assign = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_copy_assignment(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(copy_assign != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_assignment(copy_assign));
|
|
CONSTEXPR_CHECK(etl::meta::is_defaulted(copy_assign));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_move_assignment)
|
|
{
|
|
constexpr auto move_assign = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_move_assignment(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(move_assign != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_assignment(move_assign));
|
|
CONSTEXPR_CHECK(etl::meta::is_noexcept(move_assign));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_user_provided)
|
|
{
|
|
// SpecialMembers(int) is user-provided (has a body).
|
|
constexpr auto int_ctor = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_constructor(m) && !etl::meta::is_default_constructor(m) && !etl::meta::is_copy_constructor(m)
|
|
&& !etl::meta::is_move_constructor(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(int_ctor != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_user_provided(int_ctor));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_user_declared)
|
|
{
|
|
// All special members of SpecialMembers are user-declared.
|
|
constexpr auto def_ctor = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SpecialMembers, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_default_constructor(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(def_ctor != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_user_declared(def_ctor));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 4k: Value / object predicates
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_value)
|
|
{
|
|
// A reflected constant value is a value.
|
|
constexpr auto val = etl::meta::reflect_constant(42);
|
|
CONSTEXPR_CHECK(etl::meta::is_value(val));
|
|
// A type is not a value.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_value(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_object)
|
|
{
|
|
// In GCC 16, ^^variable reflects the variable, not the object.
|
|
// Use object_of to get the object reflection.
|
|
CONSTEXPR_CHECK(etl::meta::is_object(etl::meta::object_of(^^global_const)));
|
|
// A type is not an object.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_object(^^int));
|
|
// A function is not an object.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_object(^^add));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_default_member_initializer)
|
|
{
|
|
// Base::base_data has a default member initializer (= 0).
|
|
constexpr auto base_data = []() consteval
|
|
{
|
|
auto members = etl::meta::nonstatic_data_members_of(^^Base, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::identifier_of(m) == "base_data")
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(base_data != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::has_default_member_initializer(base_data));
|
|
|
|
// SimpleStruct::x has no default member initializer.
|
|
CONSTEXPR_CHECK_FALSE(
|
|
etl::meta::has_default_member_initializer(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[0]));
|
|
}
|
|
|
|
//=========================================================================
|
|
// Access context & member queries
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_access_context_unchecked)
|
|
{
|
|
// unchecked() grants access to all members, including private ones.
|
|
constexpr auto sz = []() consteval
|
|
{
|
|
auto members = etl::meta::nonstatic_data_members_of(^^MixedAccess, etl::meta::access_context::unchecked());
|
|
return members.size();
|
|
}();
|
|
CHECK_EQUAL(size_t(3), sz);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_access_context_unprivileged)
|
|
{
|
|
// unprivileged() only sees public members.
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto members = etl::meta::nonstatic_data_members_of(^^MixedAccess, etl::meta::access_context::unprivileged());
|
|
struct R
|
|
{
|
|
size_t sz;
|
|
meta_string_view name;
|
|
};
|
|
return R{members.size(), members.size() >= 1 ? etl::meta::identifier_of(members[0]) : ""};
|
|
}();
|
|
CHECK_EQUAL(size_t(1), result.sz);
|
|
CHECK(meta_string_view("pub") == result.name);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_accessible_public_member)
|
|
{
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto all = etl::meta::nonstatic_data_members_of(^^MixedAccess, etl::meta::access_context::unchecked());
|
|
struct R
|
|
{
|
|
bool pub_accessible;
|
|
bool priv_accessible;
|
|
};
|
|
return R{etl::meta::is_accessible(all[0], etl::meta::access_context::unprivileged()),
|
|
etl::meta::is_accessible(all[2], etl::meta::access_context::unprivileged())};
|
|
}();
|
|
// pub is accessible from unprivileged context.
|
|
CHECK(result.pub_accessible);
|
|
// priv is not accessible from unprivileged context.
|
|
CHECK(!result.priv_accessible);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_members_of)
|
|
{
|
|
// members_of returns all members (functions, types, data) of a class.
|
|
constexpr auto sz = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^SimpleStruct, etl::meta::access_context::unchecked());
|
|
return members.size();
|
|
}();
|
|
// SimpleStruct has at least x and y.
|
|
CHECK(sz >= size_t(2));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_bases_of)
|
|
{
|
|
// Derived has one base (Base).
|
|
constexpr auto sz = []() consteval
|
|
{
|
|
auto bases = etl::meta::bases_of(^^Derived, etl::meta::access_context::unchecked());
|
|
return bases.size();
|
|
}();
|
|
CHECK_EQUAL(size_t(1), sz);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_bases_of_no_bases)
|
|
{
|
|
// SimpleStruct has no base classes.
|
|
constexpr auto sz = []() consteval
|
|
{
|
|
auto bases = etl::meta::bases_of(^^SimpleStruct, etl::meta::access_context::unchecked());
|
|
return bases.size();
|
|
}();
|
|
CHECK_EQUAL(size_t(0), sz);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_static_data_members_of)
|
|
{
|
|
// WithStatic has one static data member (s_count).
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto statics = etl::meta::static_data_members_of(^^WithStatic, etl::meta::access_context::unchecked());
|
|
struct R
|
|
{
|
|
size_t sz;
|
|
meta_string_view name;
|
|
};
|
|
return R{statics.size(), statics.size() >= 1 ? etl::meta::identifier_of(statics[0]) : ""};
|
|
}();
|
|
CHECK_EQUAL(size_t(1), result.sz);
|
|
CHECK(meta_string_view("s_count") == result.name);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_nonstatic_data_members_of)
|
|
{
|
|
// WithStatic has one non-static data member (value).
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto nonstatics = etl::meta::nonstatic_data_members_of(^^WithStatic, etl::meta::access_context::unchecked());
|
|
struct R
|
|
{
|
|
size_t sz;
|
|
meta_string_view name;
|
|
};
|
|
return R{nonstatics.size(), nonstatics.size() >= 1 ? etl::meta::identifier_of(nonstatics[0]) : ""};
|
|
}();
|
|
CHECK_EQUAL(size_t(1), result.sz);
|
|
CHECK(meta_string_view("value") == result.name);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_enumerators_of)
|
|
{
|
|
// Color has 3 enumerators, Direction has 4.
|
|
constexpr auto color_sz = []() consteval
|
|
{
|
|
return etl::meta::enumerators_of(^^Color).size();
|
|
}();
|
|
CHECK_EQUAL(size_t(3), color_sz);
|
|
|
|
constexpr auto dir_sz = []() consteval
|
|
{
|
|
return etl::meta::enumerators_of(^^Direction).size();
|
|
}();
|
|
CHECK_EQUAL(size_t(4), dir_sz);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_inaccessible_nonstatic_data_members)
|
|
{
|
|
// MixedAccess has inaccessible members from unprivileged context.
|
|
CONSTEXPR_CHECK(etl::meta::has_inaccessible_nonstatic_data_members(^^MixedAccess, etl::meta::access_context::unprivileged()));
|
|
// SimpleStruct has no inaccessible members (all public).
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::has_inaccessible_nonstatic_data_members(^^SimpleStruct, etl::meta::access_context::unprivileged()));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_inaccessible_bases)
|
|
{
|
|
// Derived's base (Base) is public, so no inaccessible bases.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::has_inaccessible_bases(^^Derived, etl::meta::access_context::unprivileged()));
|
|
}
|
|
|
|
//=========================================================================
|
|
// substitute / can_substitute / extract
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_substitute)
|
|
{
|
|
// substitute(^^FixedArray, {^^double, reflect_constant(size_t(10))})
|
|
// should produce FixedArray<double, 10>.
|
|
constexpr auto result = etl::meta::substitute(^^FixedArray, {^^double, etl::meta::reflect_constant(size_t(10))});
|
|
CONSTEXPR_CHECK(etl::meta::is_type(result));
|
|
CONSTEXPR_CHECK(etl::meta::is_complete_type(result));
|
|
// Verify the template arguments round-trip.
|
|
constexpr auto args_check = [&]() consteval
|
|
{
|
|
auto args = etl::meta::template_arguments_of(result);
|
|
struct R
|
|
{
|
|
bool arg0_is_double;
|
|
size_t arg1;
|
|
};
|
|
return R{args[0] == ^^double, etl::meta::extract<size_t>(args[1])};
|
|
}();
|
|
CONSTEXPR_CHECK(args_check.arg0_is_double);
|
|
CHECK_EQUAL(size_t(10), args_check.arg1);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_can_substitute_valid)
|
|
{
|
|
// FixedArray<int, 3> is valid.
|
|
CONSTEXPR_CHECK(etl::meta::can_substitute(^^FixedArray, {^^int, etl::meta::reflect_constant(size_t(3))}));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_extract_int)
|
|
{
|
|
// Extract an int from a reflected constant.
|
|
constexpr auto r = etl::meta::reflect_constant(123);
|
|
constexpr int val = etl::meta::extract<int>(r);
|
|
CHECK_EQUAL(123, val);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_extract_bool)
|
|
{
|
|
constexpr auto r = etl::meta::reflect_constant(true);
|
|
constexpr bool val = etl::meta::extract<bool>(r);
|
|
CHECK(val);
|
|
}
|
|
|
|
//=========================================================================
|
|
// 17a: Primary type categories
|
|
// (These tests require substitute, which is STL-only.)
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_void_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_void_type(^^void));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_void_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_null_pointer_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_null_pointer_type(^^decltype(nullptr)));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_null_pointer_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_integral_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_integral_type(^^int));
|
|
CONSTEXPR_CHECK(etl::meta::is_integral_type(^^bool));
|
|
CONSTEXPR_CHECK(etl::meta::is_integral_type(^^char));
|
|
CONSTEXPR_CHECK(etl::meta::is_integral_type(^^unsigned long long));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_integral_type(^^double));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_integral_type(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_floating_point_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_floating_point_type(^^float));
|
|
CONSTEXPR_CHECK(etl::meta::is_floating_point_type(^^double));
|
|
CONSTEXPR_CHECK(etl::meta::is_floating_point_type(^^long double));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_floating_point_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_array_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_array_type(^^int[5]));
|
|
CONSTEXPR_CHECK(etl::meta::is_array_type(^^int[]));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_array_type(^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_array_type(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_pointer_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_pointer_type(^^int*));
|
|
CONSTEXPR_CHECK(etl::meta::is_pointer_type(^^const char*));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_pointer_type(^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_pointer_type(^^int&));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_lvalue_reference_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_lvalue_reference_type(^^int&));
|
|
CONSTEXPR_CHECK(etl::meta::is_lvalue_reference_type(^^const int&));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_lvalue_reference_type(^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_lvalue_reference_type(^^int&&));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_rvalue_reference_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_rvalue_reference_type(^^int&&));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_rvalue_reference_type(^^int&));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_rvalue_reference_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_member_object_pointer_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_member_object_pointer_type(^^int SimpleStruct::*));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_member_object_pointer_type(^^int*));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_member_function_pointer_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_member_function_pointer_type(^^void(Base::*)()));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_member_function_pointer_type(^^int SimpleStruct::*));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_enum_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_enum_type(^^Color));
|
|
CONSTEXPR_CHECK(etl::meta::is_enum_type(^^Direction));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_enum_type(^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_enum_type(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_union_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_union_type(^^TestUnion));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_union_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_union_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_class_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_class_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_class_type(^^Base));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_class_type(^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_class_type(^^Color));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_function_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_function_type(^^int(int, int)));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_function_type(^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_function_type(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_reflection_type)
|
|
{
|
|
// ^^etl::meta::info doesn't work when info is a using-declaration
|
|
// (a using-declarator cannot be reflected).
|
|
// In the std <meta> path etl::meta::info is a using-declaration for
|
|
// std::meta::info, so reflect the std name there.
|
|
// etl::meta::info is a using-declaration for std::meta::info and a
|
|
// using-declarator cannot be reflected, so reflect the std name.
|
|
CONSTEXPR_CHECK(etl::meta::is_reflection_type(^^std::meta::info));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_reflection_type(^^int));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 17b: Composite type categories
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_reference_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_reference_type(^^int&));
|
|
CONSTEXPR_CHECK(etl::meta::is_reference_type(^^int&&));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_reference_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_arithmetic_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_arithmetic_type(^^int));
|
|
CONSTEXPR_CHECK(etl::meta::is_arithmetic_type(^^double));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_arithmetic_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_arithmetic_type(^^int*));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_fundamental_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_fundamental_type(^^int));
|
|
CONSTEXPR_CHECK(etl::meta::is_fundamental_type(^^void));
|
|
CONSTEXPR_CHECK(etl::meta::is_fundamental_type(^^decltype(nullptr)));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_fundamental_type(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_object_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_object_type(^^int));
|
|
CONSTEXPR_CHECK(etl::meta::is_object_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_object_type(^^void));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_object_type(^^int&));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_scalar_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_scalar_type(^^int));
|
|
CONSTEXPR_CHECK(etl::meta::is_scalar_type(^^int*));
|
|
CONSTEXPR_CHECK(etl::meta::is_scalar_type(^^Color));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_scalar_type(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_compound_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_compound_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_compound_type(^^int*));
|
|
CONSTEXPR_CHECK(etl::meta::is_compound_type(^^int&));
|
|
CONSTEXPR_CHECK(etl::meta::is_compound_type(^^Color));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_compound_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_member_pointer_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_member_pointer_type(^^int SimpleStruct::*));
|
|
CONSTEXPR_CHECK(etl::meta::is_member_pointer_type(^^void(Base::*)()));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_member_pointer_type(^^int*));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 17c: Type properties
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_const_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_const_type(^^const int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_const_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_volatile_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_volatile_type(^^volatile int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_volatile_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_trivially_copyable_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_trivially_copyable_type(^^Trivial));
|
|
CONSTEXPR_CHECK(etl::meta::is_trivially_copyable_type(^^int));
|
|
// Polymorphic types are not trivially copyable.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_trivially_copyable_type(^^Polymorphic));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_empty_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_empty_type(^^Empty));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_empty_type(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_polymorphic_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_polymorphic_type(^^Polymorphic));
|
|
CONSTEXPR_CHECK(etl::meta::is_polymorphic_type(^^Base));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_polymorphic_type(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_abstract_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_abstract_type(^^AbstractBase));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_abstract_type(^^Base));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_abstract_type(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_final_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_final_type(^^FinalClass));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_final_type(^^Base));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_aggregate_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_aggregate_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_aggregate_type(^^Empty));
|
|
CONSTEXPR_CHECK(etl::meta::is_aggregate_type(^^Trivial));
|
|
// SpecialMembers has user-declared constructors, so it's not aggregate.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_aggregate_type(^^SpecialMembers));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_signed_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_signed_type(^^int));
|
|
CONSTEXPR_CHECK(etl::meta::is_signed_type(^^double));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_signed_type(^^unsigned int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_unsigned_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_unsigned_type(^^unsigned int));
|
|
CONSTEXPR_CHECK(etl::meta::is_unsigned_type(^^bool));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_unsigned_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_bounded_array_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_bounded_array_type(^^int[5]));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_bounded_array_type(^^int[]));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_bounded_array_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_unbounded_array_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_unbounded_array_type(^^int[]));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_unbounded_array_type(^^int[5]));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_unbounded_array_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_scoped_enum_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_scoped_enum_type(^^Color));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_scoped_enum_type(^^Direction));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_scoped_enum_type(^^int));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 17d: Constructible / assignable / destructible
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_default_constructible_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_default_constructible_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_default_constructible_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_copy_constructible_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_copy_constructible_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_copy_constructible_type(^^int));
|
|
// SpecialMembers has a deleted copy constructor.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_copy_constructible_type(^^SpecialMembers));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_move_constructible_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_move_constructible_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_move_constructible_type(^^int));
|
|
CONSTEXPR_CHECK(etl::meta::is_move_constructible_type(^^SpecialMembers));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_constructible_type)
|
|
{
|
|
// int is constructible from int.
|
|
CONSTEXPR_CHECK(etl::meta::is_constructible_type(^^int, {^^int}));
|
|
// SpecialMembers is constructible from int (explicit ctor).
|
|
CONSTEXPR_CHECK(etl::meta::is_constructible_type(^^SpecialMembers, {^^int}));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_assignable_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_assignable_type(^^int&, ^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_assignable_type(^^int, ^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_copy_assignable_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_copy_assignable_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_copy_assignable_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_move_assignable_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_move_assignable_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_move_assignable_type(^^SpecialMembers));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_destructible_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_destructible_type(^^SimpleStruct));
|
|
CONSTEXPR_CHECK(etl::meta::is_destructible_type(^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_destructible_type(^^void));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_trivially_copy_constructible_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_trivially_copy_constructible_type(^^Trivial));
|
|
CONSTEXPR_CHECK(etl::meta::is_trivially_copy_constructible_type(^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_trivially_copy_constructible_type(^^Polymorphic));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_trivially_copy_assignable_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_trivially_copy_assignable_type(^^Trivial));
|
|
CONSTEXPR_CHECK(etl::meta::is_trivially_copy_assignable_type(^^int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_trivially_destructible_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_trivially_destructible_type(^^Trivial));
|
|
CONSTEXPR_CHECK(etl::meta::is_trivially_destructible_type(^^int));
|
|
// Polymorphic has a virtual destructor, so not trivially destructible.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_trivially_destructible_type(^^Polymorphic));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 17e: Type property queries (rank, extent)
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_rank)
|
|
{
|
|
CONSTEXPR_CHECK_EQUAL(size_t(0), etl::meta::rank(^^int));
|
|
CONSTEXPR_CHECK_EQUAL(size_t(1), etl::meta::rank(^^int[5]));
|
|
CONSTEXPR_CHECK_EQUAL(size_t(2), etl::meta::rank(^^int[3][4]));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_extent)
|
|
{
|
|
CONSTEXPR_CHECK_EQUAL(size_t(5), etl::meta::extent(^^int[5]));
|
|
CONSTEXPR_CHECK_EQUAL(size_t(3), etl::meta::extent(^^int[3][4], 0));
|
|
CONSTEXPR_CHECK_EQUAL(size_t(4), etl::meta::extent(^^int[3][4], 1));
|
|
// Unbounded first dimension has extent 0.
|
|
CONSTEXPR_CHECK_EQUAL(size_t(0), etl::meta::extent(^^int[]));
|
|
}
|
|
|
|
//=========================================================================
|
|
// 17f: Type relations
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_same_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_same_type(^^int, ^^int));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_same_type(^^int, ^^double));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_same_type(^^int, ^^const int));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_base_of_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_base_of_type(^^Base, ^^Derived));
|
|
CONSTEXPR_CHECK(etl::meta::is_base_of_type(^^Base, ^^FinalClass));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_base_of_type(^^Derived, ^^Base));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_base_of_type(^^SimpleStruct, ^^Derived));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_convertible_type)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::is_convertible_type(^^int, ^^double));
|
|
CONSTEXPR_CHECK(etl::meta::is_convertible_type(^^Derived*, ^^Base*));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_convertible_type(^^Base*, ^^Derived*));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_virtual_destructor)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::has_virtual_destructor(^^Base));
|
|
CONSTEXPR_CHECK(etl::meta::has_virtual_destructor(^^Polymorphic));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::has_virtual_destructor(^^SimpleStruct));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::has_virtual_destructor(^^Trivial));
|
|
}
|
|
|
|
//=========================================================================
|
|
// Type transformations
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_remove_const)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::remove_const(^^const int) == ^^int);
|
|
// Removing const from non-const is a no-op.
|
|
CONSTEXPR_CHECK(etl::meta::remove_const(^^int) == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_remove_volatile)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::remove_volatile(^^volatile int) == ^^int);
|
|
CONSTEXPR_CHECK(etl::meta::remove_volatile(^^int) == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_remove_cv)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::remove_cv(^^const volatile int) == ^^int);
|
|
CONSTEXPR_CHECK(etl::meta::remove_cv(^^const int) == ^^int);
|
|
CONSTEXPR_CHECK(etl::meta::remove_cv(^^volatile int) == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_add_const)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::add_const(^^int) == ^^const int);
|
|
// Adding const to already-const is idempotent.
|
|
CONSTEXPR_CHECK(etl::meta::add_const(^^const int) == ^^const int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_add_volatile)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::add_volatile(^^int) == ^^volatile int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_add_cv)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::add_cv(^^int) == ^^const volatile int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_remove_reference)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::remove_reference(^^int&) == ^^int);
|
|
CONSTEXPR_CHECK(etl::meta::remove_reference(^^int&&) == ^^int);
|
|
CONSTEXPR_CHECK(etl::meta::remove_reference(^^int) == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_add_lvalue_reference)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::add_lvalue_reference(^^int) == ^^int&);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_add_rvalue_reference)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::add_rvalue_reference(^^int) == ^^int&&);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_make_signed)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::make_signed(^^unsigned int) == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_make_unsigned)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::make_unsigned(^^int) == ^^unsigned int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_remove_extent)
|
|
{
|
|
// remove_extent(int[5]) -> int
|
|
CONSTEXPR_CHECK(etl::meta::remove_extent(^^int[5]) == ^^int);
|
|
// remove_extent(int[3][4]) -> int[4]
|
|
CONSTEXPR_CHECK(etl::meta::remove_extent(^^int[3][4]) == ^^int[4]);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_remove_all_extents)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::remove_all_extents(^^int[3][4]) == ^^int);
|
|
CONSTEXPR_CHECK(etl::meta::remove_all_extents(^^int[5]) == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_remove_pointer)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::remove_pointer(^^int*) == ^^int);
|
|
CONSTEXPR_CHECK(etl::meta::remove_pointer(^^const int*) == ^^const int);
|
|
// Non-pointer is unchanged.
|
|
CONSTEXPR_CHECK(etl::meta::remove_pointer(^^int) == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_add_pointer)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::add_pointer(^^int) == ^^int*);
|
|
CONSTEXPR_CHECK(etl::meta::add_pointer(^^const int) == ^^const int*);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_remove_cvref)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::remove_cvref(^^const int&) == ^^int);
|
|
CONSTEXPR_CHECK(etl::meta::remove_cvref(^^volatile int&&) == ^^int);
|
|
CONSTEXPR_CHECK(etl::meta::remove_cvref(^^const volatile int) == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_decay)
|
|
{
|
|
// Array decays to pointer.
|
|
CONSTEXPR_CHECK(etl::meta::decay(^^int[5]) == ^^int*);
|
|
// Function decays to function pointer.
|
|
CONSTEXPR_CHECK(etl::meta::decay(^^int(int)) == ^^int (*)(int));
|
|
// CV-ref is stripped.
|
|
CONSTEXPR_CHECK(etl::meta::decay(^^const int&) == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_common_type)
|
|
{
|
|
// common_type(int, double) -> double
|
|
constexpr auto ct = etl::meta::common_type({^^int, ^^double});
|
|
CONSTEXPR_CHECK(ct == ^^double);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_underlying_type)
|
|
{
|
|
// Color is an enum class; its underlying type is int by default.
|
|
constexpr auto ut = etl::meta::underlying_type(^^Color);
|
|
CONSTEXPR_CHECK(etl::meta::is_integral_type(ut));
|
|
}
|
|
|
|
//=========================================================================
|
|
// Data layout
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_size_of_type)
|
|
{
|
|
CONSTEXPR_CHECK_EQUAL(sizeof(int), etl::meta::size_of(^^int));
|
|
CONSTEXPR_CHECK_EQUAL(sizeof(double), etl::meta::size_of(^^double));
|
|
CONSTEXPR_CHECK_EQUAL(sizeof(SimpleStruct), etl::meta::size_of(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_alignment_of_type)
|
|
{
|
|
CONSTEXPR_CHECK_EQUAL(alignof(int), etl::meta::alignment_of(^^int));
|
|
CONSTEXPR_CHECK_EQUAL(alignof(double), etl::meta::alignment_of(^^double));
|
|
CONSTEXPR_CHECK_EQUAL(alignof(SimpleStruct), etl::meta::alignment_of(^^SimpleStruct));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_bit_size_of_bit_field)
|
|
{
|
|
// BitFields::a is 3 bits, BitFields::b is 5 bits.
|
|
CONSTEXPR_CHECK_EQUAL(size_t(3),
|
|
etl::meta::bit_size_of(etl::meta::nonstatic_data_members_of(^^BitFields, etl::meta::access_context::unchecked())[0]));
|
|
CONSTEXPR_CHECK_EQUAL(size_t(5),
|
|
etl::meta::bit_size_of(etl::meta::nonstatic_data_members_of(^^BitFields, etl::meta::access_context::unchecked())[1]));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_offset_of)
|
|
{
|
|
// The first member of SimpleStruct should be at offset {0, 0}.
|
|
constexpr auto off = etl::meta::offset_of(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[0]);
|
|
CHECK_EQUAL(ptrdiff_t(0), off.bytes);
|
|
CHECK_EQUAL(ptrdiff_t(0), off.bits);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_offset_of_second_member)
|
|
{
|
|
// The second member of SimpleStruct (double y) should be at a non-zero offset.
|
|
constexpr auto off = etl::meta::offset_of(etl::meta::nonstatic_data_members_of(^^SimpleStruct, etl::meta::access_context::unchecked())[1]);
|
|
// double typically follows int with padding; offset should be > 0.
|
|
CHECK(off.bytes > ptrdiff_t(0));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_member_offset_total_bits)
|
|
{
|
|
etl::meta::member_offset off{2, 3};
|
|
CHECK_EQUAL(ptrdiff_t(2 * __CHAR_BIT__ + 3), off.total_bits());
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_member_offset_comparison)
|
|
{
|
|
etl::meta::member_offset a{0, 0};
|
|
etl::meta::member_offset b{1, 0};
|
|
CHECK(a < b);
|
|
CHECK(a == a);
|
|
CHECK(!(a == b));
|
|
}
|
|
|
|
//=========================================================================
|
|
// reflect_constant / reflect_object / reflect_function
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_reflect_constant_int)
|
|
{
|
|
constexpr auto r = etl::meta::reflect_constant(42);
|
|
constexpr int val = etl::meta::extract<int>(r);
|
|
CHECK_EQUAL(42, val);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_reflect_constant_char)
|
|
{
|
|
constexpr auto r = etl::meta::reflect_constant('A');
|
|
constexpr char val = etl::meta::extract<char>(r);
|
|
CHECK_EQUAL('A', val);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_reflect_constant_negative)
|
|
{
|
|
constexpr auto r = etl::meta::reflect_constant(-7);
|
|
constexpr int val = etl::meta::extract<int>(r);
|
|
CHECK_EQUAL(-7, val);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_reflect_object)
|
|
{
|
|
// reflect_object on global_const should give a reflection of the object.
|
|
constexpr auto r = etl::meta::reflect_object(global_const);
|
|
CONSTEXPR_CHECK(etl::meta::is_object(r));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_reflect_function)
|
|
{
|
|
// reflect_function on add should give a reflection of the function.
|
|
constexpr auto r = etl::meta::reflect_function(add);
|
|
CONSTEXPR_CHECK(etl::meta::is_function(r));
|
|
}
|
|
|
|
//=========================================================================
|
|
// define_aggregate / data_member_spec
|
|
//=========================================================================
|
|
|
|
// GCC warns about missing field initializers in designated-init of
|
|
// data_member_options, but omitted fields are intentionally defaulted.
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
|
|
|
//*************************************************************************
|
|
TEST(test_data_member_spec_basic)
|
|
{
|
|
// Create a data member spec for an int named "value".
|
|
constexpr auto spec = etl::meta::data_member_spec(^^int, {.name = "value"});
|
|
CONSTEXPR_CHECK(etl::meta::is_data_member_spec(spec));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_data_member_spec_unnamed)
|
|
{
|
|
// Create a data member spec without an explicit name (using bit-width).
|
|
// GCC 16 uses .bit_width; Bloomberg clang-p2996 uses .width.
|
|
constexpr auto spec = etl::meta::data_member_spec(^^unsigned, {.bit_width = 8});
|
|
CONSTEXPR_CHECK(etl::meta::is_data_member_spec(spec));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_data_member_spec_with_no_unique_address)
|
|
{
|
|
// Create a data member spec with no_unique_address.
|
|
constexpr auto spec = etl::meta::data_member_spec(^^int, {.name = "val", .no_unique_address = true});
|
|
CONSTEXPR_CHECK(etl::meta::is_data_member_spec(spec));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_data_member_spec_bit_field)
|
|
{
|
|
// Create a bit-field data member spec.
|
|
constexpr auto spec = etl::meta::data_member_spec(^^unsigned, {.name = "bits", .bit_width = 4});
|
|
CONSTEXPR_CHECK(etl::meta::is_data_member_spec(spec));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_define_aggregate)
|
|
{
|
|
// Define a new aggregate type with two members at compile time.
|
|
// define_aggregate must be called from a consteval { } block in GCC 16.
|
|
struct NewType;
|
|
consteval
|
|
{
|
|
etl::meta::define_aggregate(^^NewType,
|
|
{etl::meta::data_member_spec(^^int, {.name = "a"}), etl::meta::data_member_spec(^^double, {.name = "b"})});
|
|
}
|
|
// Now NewType is complete; query it in a consteval lambda.
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto new_type = ^^NewType;
|
|
bool is_type_ok = etl::meta::is_type(new_type);
|
|
bool is_complete_ok = etl::meta::is_complete_type(new_type);
|
|
|
|
auto members = etl::meta::nonstatic_data_members_of(new_type, etl::meta::access_context::unchecked());
|
|
struct R
|
|
{
|
|
size_t sz;
|
|
meta_string_view name0;
|
|
meta_string_view name1;
|
|
bool type0_is_int;
|
|
bool type1_is_double;
|
|
bool is_type;
|
|
bool is_complete;
|
|
};
|
|
return R{members.size(),
|
|
etl::meta::identifier_of(members[0]),
|
|
etl::meta::identifier_of(members[1]),
|
|
etl::meta::type_of(members[0]) == ^^int,
|
|
etl::meta::type_of(members[1]) == ^^double,
|
|
is_type_ok,
|
|
is_complete_ok};
|
|
}();
|
|
CHECK(result.is_type);
|
|
CHECK(result.is_complete);
|
|
CHECK_EQUAL(size_t(2), result.sz);
|
|
CHECK(meta_string_view("a") == result.name0);
|
|
CHECK(meta_string_view("b") == result.name1);
|
|
CHECK(result.type0_is_int);
|
|
CHECK(result.type1_is_double);
|
|
}
|
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
//=========================================================================
|
|
// Parameter reflection
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_parameters_of)
|
|
{
|
|
// add(int, int) has 2 parameters.
|
|
constexpr auto sz = []() consteval
|
|
{
|
|
return etl::meta::parameters_of(^^add).size();
|
|
}();
|
|
CHECK_EQUAL(size_t(2), sz);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_parameter_names)
|
|
{
|
|
// Parameters of add are named "a" and "b".
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto params = etl::meta::parameters_of(^^add);
|
|
struct R
|
|
{
|
|
meta_string_view name0;
|
|
meta_string_view name1;
|
|
};
|
|
return R{etl::meta::identifier_of(params[0]), etl::meta::identifier_of(params[1])};
|
|
}();
|
|
CHECK(meta_string_view("a") == result.name0);
|
|
CHECK(meta_string_view("b") == result.name1);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_function_parameter)
|
|
{
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto params = etl::meta::parameters_of(^^add);
|
|
struct R
|
|
{
|
|
bool p0;
|
|
bool p1;
|
|
};
|
|
return R{etl::meta::is_function_parameter(params[0]), etl::meta::is_function_parameter(params[1])};
|
|
}();
|
|
CHECK(result.p0);
|
|
CHECK(result.p1);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_return_type_of)
|
|
{
|
|
// add returns int.
|
|
constexpr auto ret = etl::meta::return_type_of(^^add);
|
|
CONSTEXPR_CHECK(ret == ^^int);
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_default_argument)
|
|
{
|
|
// with_default(int a, int b = 10): second param has a default.
|
|
constexpr auto result = []() consteval
|
|
{
|
|
auto params = etl::meta::parameters_of(^^with_default);
|
|
struct R
|
|
{
|
|
bool first_has_default;
|
|
bool second_has_default;
|
|
};
|
|
return R{etl::meta::has_default_argument(params[0]), etl::meta::has_default_argument(params[1])};
|
|
}();
|
|
CHECK(!result.first_has_default);
|
|
CHECK(result.second_has_default);
|
|
}
|
|
|
|
//*************************************************************************
|
|
|
|
//=========================================================================
|
|
// Edge-case tests — remaining API gaps
|
|
//=========================================================================
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_lvalue_reference_qualified)
|
|
{
|
|
// RefQualified::lref is &-qualified.
|
|
constexpr auto lref_fn = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^RefQualified, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::has_identifier(m) && etl::meta::identifier_of(m) == "lref")
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(lref_fn != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_lvalue_reference_qualified(lref_fn));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_rvalue_reference_qualified(lref_fn));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_rvalue_reference_qualified)
|
|
{
|
|
// RefQualified::rref is &&-qualified.
|
|
constexpr auto rref_fn = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^RefQualified, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::has_identifier(m) && etl::meta::identifier_of(m) == "rref")
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(rref_fn != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_rvalue_reference_qualified(rref_fn));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_lvalue_reference_qualified(rref_fn));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_no_ref_qualification)
|
|
{
|
|
// RefQualified::none has neither ref-qualification.
|
|
constexpr auto none_fn = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^RefQualified, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::has_identifier(m) && etl::meta::identifier_of(m) == "none")
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(none_fn != etl::meta::info{});
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_lvalue_reference_qualified(none_fn));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_rvalue_reference_qualified(none_fn));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_thread_storage_duration)
|
|
{
|
|
CONSTEXPR_CHECK(etl::meta::has_thread_storage_duration(^^tls_var));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::has_static_storage_duration(^^tls_var));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_has_automatic_storage_duration)
|
|
{
|
|
// A local variable inside a consteval context has automatic storage.
|
|
// We test indirectly: namespace-scope variables do NOT have automatic storage.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::has_automatic_storage_duration(^^global_const));
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::has_automatic_storage_duration(^^internal_var));
|
|
}
|
|
|
|
//*************************************************************************
|
|
//*************************************************************************
|
|
TEST(test_is_structural_type)
|
|
{
|
|
// Structural (all-public, no virtual, trivially destructible) is structural.
|
|
CONSTEXPR_CHECK(etl::meta::is_structural_type(^^Structural));
|
|
CONSTEXPR_CHECK(etl::meta::is_structural_type(^^int));
|
|
// A class with non-public non-static data members is never structural.
|
|
CONSTEXPR_CHECK_FALSE(etl::meta::is_structural_type(^^MixedAccess));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_object_of)
|
|
{
|
|
// object_of on a reflected variable returns the object it designates.
|
|
constexpr auto obj = etl::meta::object_of(^^global_const);
|
|
CONSTEXPR_CHECK(etl::meta::is_object(obj));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_conversion_function)
|
|
{
|
|
// WithConversion has a conversion operator.
|
|
constexpr auto conv = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^WithConversion, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::is_conversion_function(m))
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(conv != etl::meta::info{});
|
|
CONSTEXPR_CHECK(etl::meta::is_conversion_function(conv));
|
|
}
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_trivially_constructible_type_multi_arg)
|
|
{
|
|
// Trivial is trivially constructible from (Trivial const&).
|
|
CONSTEXPR_CHECK(etl::meta::is_trivially_constructible_type(^^Trivial, {^^const Trivial& }));
|
|
// Trivial is trivially constructible from (Trivial&&).
|
|
CONSTEXPR_CHECK(etl::meta::is_trivially_constructible_type(^^Trivial, {^^Trivial&& }));
|
|
}
|
|
|
|
//*************************************************************************
|
|
|
|
//*************************************************************************
|
|
TEST(test_is_explicit_object_parameter)
|
|
{
|
|
// WithDeducingThis::get has an explicit object parameter (deducing this).
|
|
constexpr auto get_fn = []() consteval
|
|
{
|
|
auto members = etl::meta::members_of(^^WithDeducingThis, etl::meta::access_context::unchecked());
|
|
for (auto m : members)
|
|
if (etl::meta::has_identifier(m) && etl::meta::identifier_of(m) == "get")
|
|
return m;
|
|
return etl::meta::info{};
|
|
}();
|
|
CONSTEXPR_CHECK(get_fn != etl::meta::info{});
|
|
|
|
constexpr auto result = [&]() consteval
|
|
{
|
|
auto params = etl::meta::parameters_of(get_fn);
|
|
struct R
|
|
{
|
|
size_t sz;
|
|
bool is_explicit;
|
|
};
|
|
return R{params.size(), params.size() >= 1 && etl::meta::is_explicit_object_parameter(params[0])};
|
|
}();
|
|
CHECK(result.sz >= size_t(1));
|
|
CHECK(result.is_explicit);
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
#endif // ETL_HAS_REFLECTION
|