Added C++11 alignment matcher code

This commit is contained in:
John Wellbelove 2023-06-14 08:20:36 +01:00
parent 81cd2df218
commit c9bb331f4c

View File

@ -102,16 +102,61 @@ namespace etl
namespace private_alignment
{
#if ETL_USING_CPP11
//***************************************************************************
// Matcher.
//***************************************************************************
template <bool IS_MATCH, const size_t ALIGNMENT, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
template <bool Is_Match, size_t Alignment, typename... TRest>
class type_with_alignment_matcher;
// Matching alignment.
template <size_t Alignment, typename T1, typename... TRest>
class type_with_alignment_matcher<true, Alignment, T1, TRest...>
{
public:
typedef T1 type;
};
// Non-matching alignment
template <size_t Alignment, typename T1, typename T2, typename... TRest>
class type_with_alignment_matcher <false, Alignment, T1, T2, TRest...>
{
public:
typedef typename type_with_alignment_matcher < Alignment <= etl::alignment_of<T2>::value , Alignment, T2, TRest... > ::type type;
};
// Non-matching alignment, none left.
template <size_t Alignment, typename T1>
class type_with_alignment_matcher <false, Alignment, T1>
{
public:
typedef char type;
};
//***************************************************************************
// Helper.
//***************************************************************************
template <size_t Alignment, typename T1, typename... T>
class type_with_alignment_helper
{
public:
typedef typename type_with_alignment_matcher<Alignment <= etl::alignment_of<T1>::value, Alignment, T1, T...>::type type;
};
#else
//***************************************************************************
// Matcher.
//***************************************************************************
template <bool Is_Match, const size_t Alignment, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
class type_with_alignment_matcher;
// Matching alignment.
template <size_t ALIGNMENT, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
class type_with_alignment_matcher <true, ALIGNMENT, T1, T2, T3, T4, T5, T6, T7, T8>
template <size_t Alignment, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
class type_with_alignment_matcher <true, Alignment, T1, T2, T3, T4, T5, T6, T7, T8>
{
public:
@ -119,17 +164,17 @@ namespace etl
};
// Non-matching alignment.
template <size_t ALIGNMENT, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
class type_with_alignment_matcher <false, ALIGNMENT, T1, T2, T3, T4, T5, T6, T7, T8>
template <size_t Alignment, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
class type_with_alignment_matcher <false, Alignment, T1, T2, T3, T4, T5, T6, T7, T8>
{
public:
typedef typename type_with_alignment_matcher<ALIGNMENT <= etl::alignment_of<T2>::value, ALIGNMENT, T2, T3, T4, T5, T6, T7, T8, void>::type type;
typedef typename type_with_alignment_matcher<Alignment <= etl::alignment_of<T2>::value, Alignment, T2, T3, T4, T5, T6, T7, T8, void>::type type;
};
// Non-matching alignment, none left.
template <size_t ALIGNMENT>
class type_with_alignment_matcher <false, ALIGNMENT, void, void, void, void, void, void, void, void>
template <size_t Alignment>
class type_with_alignment_matcher <false, Alignment, void, void, void, void, void, void, void, void>
{
public:
@ -139,38 +184,39 @@ namespace etl
//***************************************************************************
// Helper.
//***************************************************************************
template <size_t ALIGNMENT, typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
template <size_t Alignment, typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
class type_with_alignment_helper
{
public:
typedef typename type_with_alignment_matcher<ALIGNMENT <= etl::alignment_of<T1>::value, ALIGNMENT, T1, T2, T3, T4, T5, T6, T7, T8>::type type;
typedef typename type_with_alignment_matcher<Alignment <= etl::alignment_of<T1>::value, Alignment, T1, T2, T3, T4, T5, T6, T7, T8>::type type;
};
#endif
}
//***************************************************************************
/// Gets a type that has the same as the specified alignment.
///\ingroup alignment
//***************************************************************************
template <size_t ALIGNMENT>
template <size_t Alignment>
class type_with_alignment
{
public:
#if ETL_NOT_USING_64BIT_TYPES
typedef typename private_alignment::type_with_alignment_helper<ALIGNMENT, int_least8_t, int_least16_t, int32_t, float, double, void*>::type type;
typedef typename private_alignment::type_with_alignment_helper<Alignment, int_least8_t, int_least16_t, int32_t, float, double, void*>::type type;
#else
typedef typename private_alignment::type_with_alignment_helper<ALIGNMENT, int_least8_t, int_least16_t, int32_t, int64_t, float, double, void*>::type type;
typedef typename private_alignment::type_with_alignment_helper<Alignment, int_least8_t, int_least16_t, int32_t, int64_t, float, double, void*>::type type;
#endif
};
//***************************************************************************
/// Aligned storage
/// LENGTH should be determined in terms of sizeof()
/// Length should be determined in terms of sizeof()
///\ingroup alignment
//***************************************************************************
template <size_t LENGTH, const size_t ALIGNMENT>
template <size_t Length, const size_t Alignment>
struct aligned_storage
{
struct type
@ -184,7 +230,7 @@ namespace etl
template <typename T>
operator T& ()
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
T* t = *this;
return *t;
}
@ -193,7 +239,7 @@ namespace etl
template <typename T>
operator const T& () const
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
const T* t = *this;
return *t;
}
@ -202,7 +248,7 @@ namespace etl
template <typename T>
operator T* ()
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<T*>(data);
}
@ -210,7 +256,7 @@ namespace etl
template <typename T>
operator const T* () const
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<const T*>(data);
}
@ -218,7 +264,7 @@ namespace etl
template <typename T>
T& get_reference()
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
T* t = *this;
return *t;
}
@ -227,7 +273,7 @@ namespace etl
template <typename T>
const T& get_reference() const
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
const T* t = *this;
return *t;
}
@ -236,7 +282,7 @@ namespace etl
template <typename T>
T* get_address()
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<T*>(data);
}
@ -244,39 +290,39 @@ namespace etl
template <typename T>
const T* get_address() const
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<const T*>(data);
}
#if ETL_USING_CPP11 && !defined(ETL_COMPILER_ARM5)
alignas(ALIGNMENT) char data[LENGTH];
alignas(Alignment) char data[Length];
#else
union
{
char data[LENGTH];
typename etl::type_with_alignment<ALIGNMENT>::type etl_alignment_type; // A POD type that has the same alignment as ALIGNMENT.
char data[Length];
typename etl::type_with_alignment<Alignment>::type etl_alignment_type; // A POD type that has the same alignment as Alignment.
};
#endif
};
};
#if ETL_USING_CPP11
template <size_t LENGTH, const size_t ALIGNMENT>
using aligned_storage_t = typename aligned_storage<LENGTH, ALIGNMENT>::type;
template <size_t Length, const size_t Alignment>
using aligned_storage_t = typename aligned_storage<Length, Alignment>::type;
#endif
//***************************************************************************
/// Aligned storage as
///\ingroup alignment
//***************************************************************************
template <size_t LENGTH, typename T>
struct aligned_storage_as : public etl::aligned_storage<LENGTH, etl::alignment_of<T>::value>
template <size_t Length, typename T>
struct aligned_storage_as : public etl::aligned_storage<Length, etl::alignment_of<T>::value>
{
};
#if ETL_USING_CPP11
template <size_t LENGTH, typename T>
using aligned_storage_as_t = typename aligned_storage_as<LENGTH, T>::type;
template <size_t Length, typename T>
using aligned_storage_as_t = typename aligned_storage_as<Length, T>::type;
#endif
}