mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Added type_id
This commit is contained in:
parent
55503e0b97
commit
018a4a5c78
180
include/etl/type_id.h
Normal file
180
include/etl/type_id.h
Normal file
@ -0,0 +1,180 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2026 John Wellbelove
|
||||
|
||||
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.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_TYPE_ID_INCLUDED
|
||||
#define ETL_TYPE_ID_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
namespace private_type_id
|
||||
{
|
||||
template <typename T>
|
||||
struct type_id_anchor
|
||||
{
|
||||
static char value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
char type_id_anchor<T>::value = 0;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// A type identifier.
|
||||
/// Provides a way to identify types at runtime without using RTTI.
|
||||
//*************************************************************************
|
||||
class type_id
|
||||
{
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
/// Get the type id for the specified type.
|
||||
/// \return A type_id instance.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
static ETL_CONSTEXPR type_id get() ETL_NOEXCEPT
|
||||
{
|
||||
using type = typename etl::remove_cvref<T>::type;
|
||||
|
||||
return type_id(&private_type_id::type_id_anchor<type>::value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// The invalid type id.
|
||||
/// \return A type_id instance representing an invalid type id.
|
||||
//*************************************************************************
|
||||
static ETL_CONSTEXPR type_id invalid_id() ETL_NOEXCEPT
|
||||
{
|
||||
return type_id();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Default constructor.
|
||||
/// Sets the value of the type id to Invalid_Type_Id
|
||||
//*************************************************************************
|
||||
ETL_CONSTEXPR type_id() ETL_NOEXCEPT
|
||||
: id(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Copy constructor
|
||||
//*************************************************************************
|
||||
type_id(const type_id& other) ETL_NOEXCEPT
|
||||
: id(other.id)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Assignment operator
|
||||
/// \param other The other type_id
|
||||
/// \return Reference to the type_id
|
||||
//*************************************************************************
|
||||
type_id& operator =(const type_id& other) ETL_NOEXCEPT
|
||||
{
|
||||
id = other.id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Equality operator
|
||||
/// \param rhs The other type_id to compare with
|
||||
/// \return <b>true</b> if the type_id is equal
|
||||
//*************************************************************************
|
||||
ETL_CONSTEXPR bool operator ==(const type_id& rhs) const ETL_NOEXCEPT
|
||||
{
|
||||
return id == rhs.id;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Inequality operator
|
||||
/// \param rhs The other type_id to compare with
|
||||
/// \return <b>true</b> if the type_id is not equal
|
||||
|
||||
//*************************************************************************
|
||||
ETL_CONSTEXPR bool operator !=(const type_id& rhs) const ETL_NOEXCEPT
|
||||
{
|
||||
return !(id == rhs.id);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Less-than operator
|
||||
/// \param rhs The other type_id to compare with
|
||||
/// \return <b>true</b> if the this type_id is less than rhs
|
||||
//*************************************************************************
|
||||
bool operator <(const type_id& rhs) const ETL_NOEXCEPT
|
||||
{
|
||||
return id < rhs.id;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Conversion operator to intptr_t
|
||||
/// Explicit for C++11 and above
|
||||
//*************************************************************************
|
||||
ETL_EXPLICIT operator intptr_t() const ETL_NOEXCEPT
|
||||
{
|
||||
return reinterpret_cast<intptr_t>(id);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Conversion operator to uintptr_t
|
||||
/// Explicit for C++11 and above
|
||||
/// //*************************************************************************
|
||||
ETL_EXPLICIT operator uintptr_t() const ETL_NOEXCEPT
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(id);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Conversion operator to bool
|
||||
/// Explicit for C++11 and above
|
||||
/// \return <b>false</b> if the type_id is equal to <code>etl::type_id::Invalid_Type_Id</code>
|
||||
//*************************************************************************
|
||||
ETL_EXPLICIT ETL_CONSTEXPR operator bool() const ETL_NOEXCEPT
|
||||
{
|
||||
return id != ETL_NULLPTR;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Private construct from a void*
|
||||
ETL_CONSTEXPR type_id(void* id_) ETL_NOEXCEPT
|
||||
: id(id_)
|
||||
{
|
||||
}
|
||||
|
||||
// The id as a void*
|
||||
const void* id;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
228
test/test_type_id.cpp
Normal file
228
test/test_type_id.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
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/type_id.h"
|
||||
#include "etl/type_traits.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct A {};
|
||||
struct B {};
|
||||
struct C {};
|
||||
|
||||
SUITE(test_type_id)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(test_default_construction)
|
||||
{
|
||||
etl::type_id id_a1;;
|
||||
etl::type_id id_a2;
|
||||
|
||||
CHECK_TRUE(id_a1 == etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_a2 == etl::type_id::invalid_id());
|
||||
|
||||
CHECK_TRUE(id_a1 == id_a2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_get_same_type_returns_same_id)
|
||||
{
|
||||
etl::type_id id_a1 = etl::type_id::get<A>();
|
||||
etl::type_id id_a2 = etl::type_id::get<A>();
|
||||
|
||||
CHECK_TRUE(id_a1 != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_a2 != etl::type_id::invalid_id());
|
||||
|
||||
CHECK_TRUE(id_a1 == id_a2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_different_types_have_different_ids)
|
||||
{
|
||||
etl::type_id id_a = etl::type_id::get<A>();
|
||||
etl::type_id id_b = etl::type_id::get<B>();
|
||||
etl::type_id id_c = etl::type_id::get<C>();
|
||||
|
||||
CHECK_TRUE(id_a != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_b != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_c != etl::type_id::invalid_id());
|
||||
|
||||
CHECK_TRUE(id_a != id_b);
|
||||
CHECK_TRUE(id_a != id_c);
|
||||
CHECK_TRUE(id_b != id_c);
|
||||
|
||||
CHECK_TRUE((id_a < id_b) || (id_b < id_a));
|
||||
CHECK_TRUE((id_a < id_c) || (id_c < id_a));
|
||||
CHECK_TRUE((id_b < id_c) || (id_c < id_b));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constexpr_type_id)
|
||||
{
|
||||
constexpr etl::type_id id_a = etl::type_id::get<A>();
|
||||
constexpr etl::type_id id_b = etl::type_id::get<B>();
|
||||
constexpr etl::type_id id_c = etl::type_id::get<C>();
|
||||
|
||||
constexpr etl::type_id invalid_id = etl::type_id::invalid_id();
|
||||
|
||||
constexpr bool id_a_valid = (id_a != invalid_id);
|
||||
constexpr bool id_b_valid = (id_b != invalid_id);
|
||||
constexpr bool id_c_valid = (id_c != invalid_id);
|
||||
|
||||
constexpr bool id_a_b_not_equal = (id_a != id_b);
|
||||
constexpr bool id_a_c_not_equal = (id_a != id_c);
|
||||
constexpr bool id_b_c_not_equal = (id_b != id_c);
|
||||
|
||||
CHECK_TRUE(id_a_valid);
|
||||
CHECK_TRUE(id_b_valid);
|
||||
CHECK_TRUE(id_c_valid);
|
||||
|
||||
CHECK_TRUE(id_a_b_not_equal);
|
||||
CHECK_TRUE(id_a_c_not_equal);
|
||||
CHECK_TRUE(id_b_c_not_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_cv_and_ref_qualifiers_are_removed)
|
||||
{
|
||||
using value_type = A;
|
||||
|
||||
etl::type_id id_value = etl::type_id::get<value_type>();
|
||||
etl::type_id id_const = etl::type_id::get<const value_type>();
|
||||
etl::type_id id_volatile = etl::type_id::get<volatile value_type>();
|
||||
etl::type_id id_const_volatile = etl::type_id::get<const volatile value_type>();
|
||||
|
||||
etl::type_id id_ref = etl::type_id::get<value_type&>();
|
||||
etl::type_id id_const_ref = etl::type_id::get<const value_type&>();
|
||||
etl::type_id id_volatile_ref = etl::type_id::get<volatile value_type&>();
|
||||
etl::type_id id_cv_ref = etl::type_id::get<const volatile value_type&>();
|
||||
|
||||
CHECK_TRUE(id_value != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_const != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_volatile != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_const_volatile != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_ref != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_const_ref != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_volatile_ref != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_cv_ref != etl::type_id::invalid_id());
|
||||
|
||||
// All cv/ref variations of A should map to the same underlying id
|
||||
CHECK_TRUE(id_value == id_const);
|
||||
CHECK_TRUE(id_value == id_volatile);
|
||||
CHECK_TRUE(id_value == id_const_volatile);
|
||||
CHECK_TRUE(id_value == id_ref);
|
||||
CHECK_TRUE(id_value == id_const_ref);
|
||||
CHECK_TRUE(id_value == id_volatile_ref);
|
||||
CHECK_TRUE(id_value == id_cv_ref);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_pointer_types_have_consistent_ids)
|
||||
{
|
||||
using value_type = A;
|
||||
|
||||
etl::type_id id_value = etl::type_id::get<value_type>();
|
||||
etl::type_id id_ptr = etl::type_id::get<value_type*>();
|
||||
etl::type_id id_const_ptr = etl::type_id::get<value_type* const>();
|
||||
etl::type_id id_volatile_ptr = etl::type_id::get<value_type* volatile>();
|
||||
etl::type_id id_cv_ptr = etl::type_id::get<value_type* const volatile>();
|
||||
|
||||
CHECK_TRUE(id_value != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_ptr != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_const_ptr != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_volatile_ptr != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_cv_ptr != etl::type_id::invalid_id());
|
||||
|
||||
// All cv variations of A* should map to the same underlying pointer id
|
||||
CHECK_TRUE(id_ptr == id_const_ptr);
|
||||
CHECK_TRUE(id_ptr == id_volatile_ptr);
|
||||
CHECK_TRUE(id_ptr == id_cv_ptr);
|
||||
|
||||
// But pointer id must be distinct from the non-pointer A id
|
||||
CHECK_TRUE(id_value != id_ptr);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_different_underlying_types_remain_distinct_with_cvref)
|
||||
{
|
||||
etl::type_id id_a = etl::type_id::get<A>();
|
||||
etl::type_id id_a_const = etl::type_id::get<const A&>();
|
||||
etl::type_id id_b = etl::type_id::get<B>();
|
||||
etl::type_id id_b_const = etl::type_id::get<const B&>();
|
||||
|
||||
CHECK_TRUE(id_a != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_a_const != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_b != etl::type_id::invalid_id());
|
||||
CHECK_TRUE(id_b_const != etl::type_id::invalid_id());
|
||||
|
||||
CHECK_TRUE(id_a == id_a_const);
|
||||
CHECK_TRUE(id_b == id_b_const);
|
||||
CHECK_TRUE(id_a != id_b);
|
||||
CHECK_TRUE(id_a_const != id_b_const);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_conversion_operators)
|
||||
{
|
||||
etl::type_id id_a1 = etl::type_id::get<A>();
|
||||
etl::type_id id_a2 = etl::type_id::get<A>();
|
||||
etl::type_id id_b1 = etl::type_id::get<B>();
|
||||
etl::type_id id_b2 = etl::type_id::get<B>();
|
||||
|
||||
constexpr etl::type_id id_c1;
|
||||
constexpr etl::type_id id_c2 = etl::type_id::get<A>();
|
||||
constexpr etl::type_id id_c3 = etl::type_id::get<B>();
|
||||
|
||||
intptr_t intptr_a1 = intptr_t(id_a1);
|
||||
intptr_t intptr_a2 = intptr_t(id_a2);
|
||||
intptr_t intptr_b1 = intptr_t(id_b1);
|
||||
intptr_t intptr_b2 = intptr_t(id_b2);
|
||||
|
||||
uintptr_t uintptr_a1 = uintptr_t(id_a1);
|
||||
uintptr_t uintptr_a2 = uintptr_t(id_a2);
|
||||
uintptr_t uintptr_b1 = uintptr_t(id_b1);
|
||||
uintptr_t uintptr_b2 = uintptr_t(id_b2);
|
||||
|
||||
constexpr bool id_c1_bool = bool(id_c1);
|
||||
constexpr bool id_c2_bool = bool(id_c2);
|
||||
constexpr bool id_c3_bool = bool(id_c3);
|
||||
|
||||
CHECK_TRUE(intptr_a1 == intptr_a2);
|
||||
CHECK_TRUE(intptr_b1 == intptr_b2);
|
||||
CHECK_TRUE(intptr_a1 != intptr_b1);
|
||||
|
||||
CHECK_TRUE(uintptr_a1 == uintptr_a2);
|
||||
CHECK_TRUE(uintptr_b1 == uintptr_b2);
|
||||
CHECK_TRUE(uintptr_a1 != uintptr_b1);
|
||||
|
||||
CHECK_FALSE(id_c1_bool);
|
||||
CHECK_TRUE(id_c2_bool);
|
||||
CHECK_TRUE(id_c3_bool);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11406,6 +11406,7 @@
|
||||
<ClCompile Include="..\test_to_wstring.cpp" />
|
||||
<ClCompile Include="..\test_tuple.cpp" />
|
||||
<ClCompile Include="..\test_type_def.cpp" />
|
||||
<ClCompile Include="..\test_type_id.cpp" />
|
||||
<ClCompile Include="..\test_type_list.cpp" />
|
||||
<ClCompile Include="..\test_type_lookup.cpp" />
|
||||
<ClCompile Include="..\test_type_select.cpp" />
|
||||
|
||||
@ -3770,6 +3770,9 @@
|
||||
<ClCompile Include="..\test_inplace_function.cpp">
|
||||
<Filter>Tests\Callbacks & Delegates</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_type_id.cpp">
|
||||
<Filter>Tests\Types</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\library.properties">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user