mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Restrict etl::atomic for general types (#1359)
* Print test names at test time (#1343) * Restrict etl::atomic for general types Needs adding is_copy_assignable and is_move_assignable, and adjustments to is_trivially_copyable and is_assignable * Resolve mutable T value vs. volatile qualified methods * Remove volatile method overloads They are deprecated in C++20 because they don't work as users expect anyway. MSVC hinted for this. --------- Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
This commit is contained in:
parent
31b87b5419
commit
2f242e37f2
@ -807,6 +807,13 @@ namespace etl
|
||||
{
|
||||
public:
|
||||
|
||||
ETL_STATIC_ASSERT((etl::is_trivially_copyable<T>::value), "atomic<T> requires that T is trivially copyable");
|
||||
ETL_STATIC_ASSERT((etl::is_copy_constructible<T>::value), "atomic<T> requires that T is copy constructible");
|
||||
ETL_STATIC_ASSERT((etl::is_copy_assignable<T>::value), "atomic<T> requires that T is copy assignable");
|
||||
ETL_STATIC_ASSERT((etl::is_move_constructible<T>::value), "atomic<T> requires that T is move constructible");
|
||||
ETL_STATIC_ASSERT((etl::is_move_assignable<T>::value), "atomic<T> requires that T is move assignable");
|
||||
ETL_STATIC_ASSERT((etl::is_same<T, typename etl::remove_cv<T>::type>::value), "atomic<T> requires that T is not const or volatile");
|
||||
|
||||
atomic()
|
||||
: flag(0)
|
||||
, value(T())
|
||||
@ -827,13 +834,6 @@ namespace etl
|
||||
return v;
|
||||
}
|
||||
|
||||
T operator =(T v) volatile
|
||||
{
|
||||
store(v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
// Conversion operator
|
||||
operator T () const
|
||||
{
|
||||
@ -844,26 +844,12 @@ namespace etl
|
||||
return result;
|
||||
}
|
||||
|
||||
operator T() volatile const
|
||||
{
|
||||
ETL_BUILTIN_LOCK;
|
||||
T result = value;
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Is lock free?
|
||||
bool is_lock_free() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_lock_free() const volatile
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store
|
||||
void store(T v, etl::memory_order order = etl::memory_order_seq_cst)
|
||||
{
|
||||
@ -873,25 +859,6 @@ namespace etl
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
}
|
||||
|
||||
void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
|
||||
{
|
||||
(void)order;
|
||||
ETL_BUILTIN_LOCK;
|
||||
value = v;
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
}
|
||||
|
||||
// Load
|
||||
T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile
|
||||
{
|
||||
(void)order;
|
||||
ETL_BUILTIN_LOCK;
|
||||
T result = value;
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Load
|
||||
T load(etl::memory_order order = etl::memory_order_seq_cst) const
|
||||
{
|
||||
@ -915,17 +882,6 @@ namespace etl
|
||||
return result;
|
||||
}
|
||||
|
||||
T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
|
||||
{
|
||||
(void)order;
|
||||
ETL_BUILTIN_LOCK;
|
||||
T result = value;
|
||||
value = v;
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compare exchange weak
|
||||
bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
|
||||
{
|
||||
@ -947,26 +903,6 @@ namespace etl
|
||||
return result;
|
||||
}
|
||||
|
||||
bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile
|
||||
{
|
||||
bool result;
|
||||
|
||||
(void)order;
|
||||
ETL_BUILTIN_LOCK;
|
||||
if (memcmp(&value, &expected, sizeof(T)) == 0)
|
||||
{
|
||||
value = desired;
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
|
||||
{
|
||||
(void)success;
|
||||
@ -974,13 +910,6 @@ namespace etl
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile
|
||||
{
|
||||
(void)success;
|
||||
(void)failure;
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
// Compare exchange strong
|
||||
bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
|
||||
{
|
||||
@ -988,12 +917,6 @@ namespace etl
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile
|
||||
{
|
||||
(void)order;
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
|
||||
{
|
||||
(void)success;
|
||||
@ -1001,15 +924,11 @@ namespace etl
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile
|
||||
{
|
||||
(void)success;
|
||||
(void)failure;
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic& operator =(const atomic&) ETL_DELETE;
|
||||
atomic& operator =(const atomic&) volatile ETL_DELETE;
|
||||
|
||||
mutable char flag;
|
||||
mutable T value;
|
||||
};
|
||||
@ -1995,6 +1914,13 @@ namespace etl
|
||||
{
|
||||
public:
|
||||
|
||||
ETL_STATIC_ASSERT((etl::is_trivially_copyable<T>::value), "atomic<T> requires that T is trivially copyable");
|
||||
ETL_STATIC_ASSERT((etl::is_copy_constructible<T>::value), "atomic<T> requires that T is copy constructible");
|
||||
ETL_STATIC_ASSERT((etl::is_copy_assignable<T>::value), "atomic<T> requires that T is copy assignable");
|
||||
ETL_STATIC_ASSERT((etl::is_move_constructible<T>::value), "atomic<T> requires that T is move constructible");
|
||||
ETL_STATIC_ASSERT((etl::is_move_assignable<T>::value), "atomic<T> requires that T is move assignable");
|
||||
ETL_STATIC_ASSERT((etl::is_same<T, typename etl::remove_cv<T>::type>::value), "atomic<T> requires that T is not const or volatile");
|
||||
|
||||
atomic()
|
||||
: flag(0)
|
||||
, value(T())
|
||||
@ -2015,13 +1941,6 @@ namespace etl
|
||||
return v;
|
||||
}
|
||||
|
||||
T operator =(T v) volatile
|
||||
{
|
||||
store(v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
// Conversion operator
|
||||
operator T () const
|
||||
{
|
||||
@ -2032,26 +1951,12 @@ namespace etl
|
||||
return result;
|
||||
}
|
||||
|
||||
operator T() volatile const
|
||||
{
|
||||
ETL_BUILTIN_LOCK;
|
||||
T result = value;
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Is lock free?
|
||||
bool is_lock_free() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_lock_free() const volatile
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store
|
||||
void store(T v, etl::memory_order order = etl::memory_order_seq_cst)
|
||||
{
|
||||
@ -2060,23 +1965,6 @@ namespace etl
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
}
|
||||
|
||||
void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
|
||||
{
|
||||
ETL_BUILTIN_LOCK;
|
||||
value = v;
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
}
|
||||
|
||||
// Load
|
||||
T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile
|
||||
{
|
||||
ETL_BUILTIN_LOCK;
|
||||
T result = value;
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Load
|
||||
T load(etl::memory_order order = etl::memory_order_seq_cst) const
|
||||
{
|
||||
@ -2098,16 +1986,6 @@ namespace etl
|
||||
return result;
|
||||
}
|
||||
|
||||
T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
|
||||
{
|
||||
ETL_BUILTIN_LOCK;
|
||||
T result = value;
|
||||
value = v;
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compare exchange weak
|
||||
bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
|
||||
{
|
||||
@ -2128,58 +2006,27 @@ namespace etl
|
||||
return result;
|
||||
}
|
||||
|
||||
bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile
|
||||
{
|
||||
bool result;
|
||||
|
||||
ETL_BUILTIN_LOCK;
|
||||
if (memcmp(&value, &expected, sizeof(T)) == 0)
|
||||
{
|
||||
value = desired;
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
ETL_BUILTIN_UNLOCK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
|
||||
{
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile
|
||||
{
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
// Compare exchange strong
|
||||
bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
|
||||
{
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile
|
||||
{
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
|
||||
{
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile
|
||||
{
|
||||
return compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic& operator =(const atomic&) ETL_DELETE;
|
||||
atomic& operator =(const atomic&) volatile ETL_DELETE;
|
||||
|
||||
mutable char flag;
|
||||
mutable T value;
|
||||
};
|
||||
|
||||
@ -1929,6 +1929,16 @@ typedef integral_constant<bool, true> true_type;
|
||||
template <typename T>
|
||||
using is_move_constructible = std::is_move_constructible<T>;
|
||||
|
||||
//*********************************************
|
||||
// is_copy_assignable
|
||||
template <typename T>
|
||||
using is_copy_assignable = std::is_copy_assignable<T>;
|
||||
|
||||
//*********************************************
|
||||
// is_move_assignable
|
||||
template <typename T>
|
||||
using is_move_assignable = std::is_move_assignable<T>;
|
||||
|
||||
//*********************************************
|
||||
// is_trivially_constructible
|
||||
#if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED
|
||||
@ -1974,6 +1984,9 @@ typedef integral_constant<bool, true> true_type;
|
||||
#if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED
|
||||
template <typename T>
|
||||
using is_trivially_copyable = std::is_trivially_copyable<T>;
|
||||
#elif ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE
|
||||
template <typename T>
|
||||
using is_trivially_copyable = etl::bool_constant<__is_trivially_copyable(T)>;
|
||||
#else
|
||||
template <typename T>
|
||||
using is_trivially_copyable = etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>;
|
||||
@ -2033,6 +2046,29 @@ typedef integral_constant<bool, true> true_type;
|
||||
{
|
||||
};
|
||||
|
||||
//*********************************************
|
||||
// is_copy_assignable
|
||||
template <typename T>
|
||||
struct is_copy_assignable : public etl::is_assignable<typename etl::add_lvalue_reference<T>::type,
|
||||
typename etl::add_lvalue_reference<const T>::type>
|
||||
{
|
||||
};
|
||||
|
||||
//*********************************************
|
||||
// is_move_assignable
|
||||
#if ETL_USING_CPP11
|
||||
template <typename T>
|
||||
struct is_move_assignable : public etl::is_assignable<typename etl::add_lvalue_reference<T>::type,
|
||||
typename etl::add_rvalue_reference<T>::type>
|
||||
{
|
||||
};
|
||||
#else
|
||||
template <typename T>
|
||||
struct is_move_assignable : public etl::is_assignable<typename etl::add_lvalue_reference<T>::type, T>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************
|
||||
// is_trivially_constructible
|
||||
@ -2107,11 +2143,7 @@ typedef integral_constant<bool, true> true_type;
|
||||
template <typename T>
|
||||
struct is_trivially_copyable
|
||||
{
|
||||
#if defined(ETL_COMPILER_GCC)
|
||||
static ETL_CONSTANT bool value = __has_trivial_copy(T);
|
||||
#else
|
||||
static ETL_CONSTANT bool value = __is_trivially_copyable(T);
|
||||
#endif
|
||||
};
|
||||
|
||||
#elif defined(ETL_USER_DEFINED_TYPE_TRAITS) && !defined(ETL_USE_TYPE_TRAITS_BUILTINS)
|
||||
@ -2182,6 +2214,32 @@ typedef integral_constant<bool, true> true_type;
|
||||
template <typename T>
|
||||
struct is_move_constructible<T, false>;
|
||||
|
||||
//*********************************************
|
||||
// is_copy_assignable
|
||||
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
|
||||
struct is_copy_assignable;
|
||||
|
||||
template <typename T>
|
||||
struct is_copy_assignable<T, true> : public etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_copy_assignable<T, false>;
|
||||
|
||||
//*********************************************
|
||||
// is_move_assignable
|
||||
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
|
||||
struct is_move_assignable;
|
||||
|
||||
template <typename T>
|
||||
struct is_move_assignable<T, true> : public etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_move_assignable<T, false>;
|
||||
|
||||
//*********************************************
|
||||
// is_trivially_constructible
|
||||
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
|
||||
@ -2257,7 +2315,11 @@ typedef integral_constant<bool, true> true_type;
|
||||
//*********************************************
|
||||
// is_assignable
|
||||
template <typename T1, typename T2>
|
||||
#if ETL_USING_BUILTIN_IS_ASSIGNABLE
|
||||
struct is_assignable : public etl::bool_constant<__is_assignable(T1, T2)>
|
||||
#else
|
||||
struct is_assignable : public etl::bool_constant<(etl::is_arithmetic<T1>::value || etl::is_pointer<T1>::value) && (etl::is_arithmetic<T2>::value || etl::is_pointer<T2>::value)>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
@ -2311,6 +2373,31 @@ typedef integral_constant<bool, true> true_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
//*********************************************
|
||||
// is_copy_assignable
|
||||
template <typename T>
|
||||
struct is_copy_assignable : public etl::is_assignable<typename etl::add_lvalue_reference<T>::type,
|
||||
typename etl::add_lvalue_reference<const T>::type>
|
||||
{
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************
|
||||
// is_move_assignable
|
||||
template <typename T>
|
||||
struct is_move_assignable : public etl::is_assignable<typename etl::add_lvalue_reference<T>::type,
|
||||
typename etl::add_rvalue_reference<T>::type>
|
||||
{
|
||||
};
|
||||
#else
|
||||
//*********************************************
|
||||
// is_move_assignable
|
||||
template <typename T>
|
||||
struct is_move_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
//*********************************************
|
||||
// is_trivially_constructible
|
||||
template <typename T>
|
||||
@ -2342,7 +2429,11 @@ typedef integral_constant<bool, true> true_type;
|
||||
//*********************************************
|
||||
// is_trivially_copyable
|
||||
template <typename T>
|
||||
#if ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE
|
||||
struct is_trivially_copyable : public etl::bool_constant<__is_trivially_copyable(T)>
|
||||
#else
|
||||
struct is_trivially_copyable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
@ -2389,6 +2480,12 @@ typedef integral_constant<bool, true> true_type;
|
||||
template<typename T>
|
||||
inline constexpr bool is_move_constructible_v = etl::is_move_constructible<T>::value;
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_copy_assignable_v = etl::is_copy_assignable<T>::value;
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_move_assignable_v = etl::is_move_assignable<T>::value;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_trivially_constructible_v = etl::is_trivially_constructible<T>::value;
|
||||
|
||||
|
||||
@ -1922,6 +1922,16 @@ typedef integral_constant<bool, true> true_type;
|
||||
template <typename T>
|
||||
using is_move_constructible = std::is_move_constructible<T>;
|
||||
|
||||
//*********************************************
|
||||
// is_copy_assignable
|
||||
template <typename T>
|
||||
using is_copy_assignable = std::is_copy_assignable<T>;
|
||||
|
||||
//*********************************************
|
||||
// is_move_assignable
|
||||
template <typename T>
|
||||
using is_move_assignable = std::is_move_assignable<T>;
|
||||
|
||||
//*********************************************
|
||||
// is_trivially_constructible
|
||||
#if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED
|
||||
@ -1967,6 +1977,9 @@ typedef integral_constant<bool, true> true_type;
|
||||
#if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED
|
||||
template <typename T>
|
||||
using is_trivially_copyable = std::is_trivially_copyable<T>;
|
||||
#elif ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE
|
||||
template <typename T>
|
||||
using is_trivially_copyable = etl::bool_constant<__is_trivially_copyable(T)>;
|
||||
#else
|
||||
template <typename T>
|
||||
using is_trivially_copyable = etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>;
|
||||
@ -2026,6 +2039,29 @@ typedef integral_constant<bool, true> true_type;
|
||||
{
|
||||
};
|
||||
|
||||
//*********************************************
|
||||
// is_copy_assignable
|
||||
template <typename T>
|
||||
struct is_copy_assignable : public etl::is_assignable<typename etl::add_lvalue_reference<T>::type,
|
||||
typename etl::add_lvalue_reference<const T>::type>
|
||||
{
|
||||
};
|
||||
|
||||
//*********************************************
|
||||
// is_move_assignable
|
||||
#if ETL_USING_CPP11
|
||||
template <typename T>
|
||||
struct is_move_assignable : public etl::is_assignable<typename etl::add_lvalue_reference<T>::type,
|
||||
typename etl::add_rvalue_reference<T>::type>
|
||||
{
|
||||
};
|
||||
#else
|
||||
template <typename T>
|
||||
struct is_move_assignable : public etl::is_assignable<typename etl::add_lvalue_reference<T>::type, T>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************
|
||||
// is_trivially_constructible
|
||||
@ -2100,11 +2136,7 @@ typedef integral_constant<bool, true> true_type;
|
||||
template <typename T>
|
||||
struct is_trivially_copyable
|
||||
{
|
||||
#if defined(ETL_COMPILER_GCC)
|
||||
static ETL_CONSTANT bool value = __has_trivial_copy(T);
|
||||
#else
|
||||
static ETL_CONSTANT bool value = __is_trivially_copyable(T);
|
||||
#endif
|
||||
};
|
||||
|
||||
#elif defined(ETL_USER_DEFINED_TYPE_TRAITS) && !defined(ETL_USE_TYPE_TRAITS_BUILTINS)
|
||||
@ -2175,6 +2207,32 @@ typedef integral_constant<bool, true> true_type;
|
||||
template <typename T>
|
||||
struct is_move_constructible<T, false>;
|
||||
|
||||
//*********************************************
|
||||
// is_copy_assignable
|
||||
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
|
||||
struct is_copy_assignable;
|
||||
|
||||
template <typename T>
|
||||
struct is_copy_assignable<T, true> : public etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_copy_assignable<T, false>;
|
||||
|
||||
//*********************************************
|
||||
// is_move_assignable
|
||||
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
|
||||
struct is_move_assignable;
|
||||
|
||||
template <typename T>
|
||||
struct is_move_assignable<T, true> : public etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_move_assignable<T, false>;
|
||||
|
||||
//*********************************************
|
||||
// is_trivially_constructible
|
||||
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
|
||||
@ -2250,7 +2308,11 @@ typedef integral_constant<bool, true> true_type;
|
||||
//*********************************************
|
||||
// is_assignable
|
||||
template <typename T1, typename T2>
|
||||
#if ETL_USING_BUILTIN_IS_ASSIGNABLE
|
||||
struct is_assignable : public etl::bool_constant<__is_assignable(T1, T2)>
|
||||
#else
|
||||
struct is_assignable : public etl::bool_constant<(etl::is_arithmetic<T1>::value || etl::is_pointer<T1>::value) && (etl::is_arithmetic<T2>::value || etl::is_pointer<T2>::value)>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
@ -2304,6 +2366,31 @@ typedef integral_constant<bool, true> true_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
//*********************************************
|
||||
// is_copy_assignable
|
||||
template <typename T>
|
||||
struct is_copy_assignable : public etl::is_assignable<typename etl::add_lvalue_reference<T>::type,
|
||||
typename etl::add_lvalue_reference<const T>::type>
|
||||
{
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************
|
||||
// is_move_assignable
|
||||
template <typename T>
|
||||
struct is_move_assignable : public etl::is_assignable<typename etl::add_lvalue_reference<T>::type,
|
||||
typename etl::add_rvalue_reference<T>::type>
|
||||
{
|
||||
};
|
||||
#else
|
||||
//*********************************************
|
||||
// is_move_assignable
|
||||
template <typename T>
|
||||
struct is_move_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
//*********************************************
|
||||
// is_trivially_constructible
|
||||
template <typename T>
|
||||
@ -2335,7 +2422,11 @@ typedef integral_constant<bool, true> true_type;
|
||||
//*********************************************
|
||||
// is_trivially_copyable
|
||||
template <typename T>
|
||||
#if ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE
|
||||
struct is_trivially_copyable : public etl::bool_constant<__is_trivially_copyable(T)>
|
||||
#else
|
||||
struct is_trivially_copyable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
@ -2382,6 +2473,12 @@ typedef integral_constant<bool, true> true_type;
|
||||
template<typename T>
|
||||
inline constexpr bool is_move_constructible_v = etl::is_move_constructible<T>::value;
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_copy_assignable_v = etl::is_copy_assignable<T>::value;
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_move_assignable_v = etl::is_move_assignable<T>::value;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_trivially_constructible_v = etl::is_trivially_constructible<T>::value;
|
||||
|
||||
|
||||
@ -711,6 +711,130 @@ namespace
|
||||
CHECK_EQUAL(compare.load(), test.load());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_atomic_non_scalar_trivially_copyable_struct)
|
||||
{
|
||||
struct Data
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
|
||||
bool operator ==(const Data& other) const
|
||||
{
|
||||
return (x == other.x) && (y == other.y);
|
||||
}
|
||||
};
|
||||
|
||||
// Default construction
|
||||
etl::atomic<Data> test;
|
||||
|
||||
Data d1 = { 1, 2 };
|
||||
Data d2 = { 3, 4 };
|
||||
Data d3 = { 5, 6 };
|
||||
|
||||
// Store and load
|
||||
test.store(d1);
|
||||
Data loaded = test.load();
|
||||
CHECK_EQUAL(d1.x, loaded.x);
|
||||
CHECK_EQUAL(d1.y, loaded.y);
|
||||
|
||||
// Assignment operator
|
||||
test = d2;
|
||||
loaded = test.load();
|
||||
CHECK_EQUAL(d2.x, loaded.x);
|
||||
CHECK_EQUAL(d2.y, loaded.y);
|
||||
|
||||
// Conversion operator
|
||||
test.store(d1);
|
||||
Data converted = static_cast<Data>(test);
|
||||
CHECK_EQUAL(d1.x, converted.x);
|
||||
CHECK_EQUAL(d1.y, converted.y);
|
||||
|
||||
// Exchange
|
||||
test.store(d1);
|
||||
Data old_val = test.exchange(d2);
|
||||
CHECK_EQUAL(d1.x, old_val.x);
|
||||
CHECK_EQUAL(d1.y, old_val.y);
|
||||
loaded = test.load();
|
||||
CHECK_EQUAL(d2.x, loaded.x);
|
||||
CHECK_EQUAL(d2.y, loaded.y);
|
||||
|
||||
// Compare exchange weak - pass (expected matches)
|
||||
test.store(d1);
|
||||
Data expected = d1;
|
||||
bool result = test.compare_exchange_weak(expected, d3);
|
||||
CHECK_TRUE(result);
|
||||
loaded = test.load();
|
||||
CHECK_EQUAL(d3.x, loaded.x);
|
||||
CHECK_EQUAL(d3.y, loaded.y);
|
||||
|
||||
// Compare exchange weak - fail (expected does not match)
|
||||
test.store(d1);
|
||||
expected = d2;
|
||||
result = test.compare_exchange_weak(expected, d3);
|
||||
CHECK_FALSE(result);
|
||||
loaded = test.load();
|
||||
CHECK_EQUAL(d1.x, loaded.x);
|
||||
CHECK_EQUAL(d1.y, loaded.y);
|
||||
|
||||
// Compare exchange weak with two memory order args - pass
|
||||
test.store(d1);
|
||||
expected = d1;
|
||||
result = test.compare_exchange_weak(expected, d2, etl::memory_order_seq_cst, etl::memory_order_seq_cst);
|
||||
CHECK_TRUE(result);
|
||||
loaded = test.load();
|
||||
CHECK_EQUAL(d2.x, loaded.x);
|
||||
CHECK_EQUAL(d2.y, loaded.y);
|
||||
|
||||
// Compare exchange strong - pass (expected matches)
|
||||
test.store(d1);
|
||||
expected = d1;
|
||||
result = test.compare_exchange_strong(expected, d3);
|
||||
CHECK_TRUE(result);
|
||||
loaded = test.load();
|
||||
CHECK_EQUAL(d3.x, loaded.x);
|
||||
CHECK_EQUAL(d3.y, loaded.y);
|
||||
|
||||
// Compare exchange strong - fail (expected does not match)
|
||||
test.store(d1);
|
||||
expected = d2;
|
||||
result = test.compare_exchange_strong(expected, d3);
|
||||
CHECK_FALSE(result);
|
||||
loaded = test.load();
|
||||
CHECK_EQUAL(d1.x, loaded.x);
|
||||
CHECK_EQUAL(d1.y, loaded.y);
|
||||
|
||||
// Compare exchange strong with two memory order args - pass
|
||||
test.store(d1);
|
||||
expected = d1;
|
||||
result = test.compare_exchange_strong(expected, d2, etl::memory_order_seq_cst, etl::memory_order_seq_cst);
|
||||
CHECK_TRUE(result);
|
||||
loaded = test.load();
|
||||
CHECK_EQUAL(d2.x, loaded.x);
|
||||
CHECK_EQUAL(d2.y, loaded.y);
|
||||
|
||||
// Explicit memory order on store/load
|
||||
test.store(d3, etl::memory_order_release);
|
||||
loaded = test.load(etl::memory_order_acquire);
|
||||
CHECK_EQUAL(d3.x, loaded.x);
|
||||
CHECK_EQUAL(d3.y, loaded.y);
|
||||
|
||||
// Exchange with explicit memory order
|
||||
test.store(d1);
|
||||
old_val = test.exchange(d2, etl::memory_order_acq_rel);
|
||||
CHECK_EQUAL(d1.x, old_val.x);
|
||||
CHECK_EQUAL(d1.y, old_val.y);
|
||||
loaded = test.load();
|
||||
CHECK_EQUAL(d2.x, loaded.x);
|
||||
CHECK_EQUAL(d2.y, loaded.y);
|
||||
|
||||
// Value construction
|
||||
etl::atomic<Data> test2(d1);
|
||||
loaded = test2.load();
|
||||
CHECK_EQUAL(d1.x, loaded.x);
|
||||
CHECK_EQUAL(d1.y, loaded.y);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
#if REALTIME_TEST
|
||||
|
||||
|
||||
@ -210,6 +210,8 @@ using etl::is_assignable;
|
||||
using etl::is_constructible;
|
||||
using etl::is_copy_constructible;
|
||||
using etl::is_move_constructible;
|
||||
using etl::is_copy_assignable;
|
||||
using etl::is_move_assignable;
|
||||
|
||||
//*************************
|
||||
template <>
|
||||
@ -227,6 +229,16 @@ struct etl::is_move_constructible<Copyable> : public etl::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct etl::is_copy_assignable<Copyable> : public etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct etl::is_move_assignable<Copyable> : public etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
//*************************
|
||||
template <>
|
||||
struct etl::is_assignable<Moveable, Moveable> : public etl::true_type
|
||||
@ -243,6 +255,16 @@ struct etl::is_move_constructible<Moveable> : public etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct etl::is_copy_assignable<Moveable> : public etl::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct etl::is_move_assignable<Moveable> : public etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
//*************************
|
||||
template <>
|
||||
struct etl::is_assignable<MoveableCopyable, MoveableCopyable> : public etl::true_type
|
||||
@ -258,6 +280,16 @@ template <>
|
||||
struct etl::is_move_constructible<MoveableCopyable> : public etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct etl::is_copy_assignable<MoveableCopyable> : public etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct etl::is_move_assignable<MoveableCopyable> : public etl::true_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace
|
||||
@ -1296,6 +1328,34 @@ namespace
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_is_copy_assignable)
|
||||
{
|
||||
#if ETL_USING_CPP17
|
||||
CHECK((etl::is_copy_assignable_v<Copyable>) == (std::is_copy_assignable_v<Copyable>));
|
||||
CHECK((etl::is_copy_assignable_v<Moveable>) == (std::is_copy_assignable_v<Moveable>));
|
||||
CHECK((etl::is_copy_assignable_v<MoveableCopyable>) == (std::is_copy_assignable_v<MoveableCopyable>));
|
||||
#else
|
||||
CHECK((etl::is_copy_assignable<Copyable>::value) == (std::is_copy_assignable<Copyable>::value));
|
||||
CHECK((etl::is_copy_assignable<Moveable>::value) == (std::is_copy_assignable<Moveable>::value));
|
||||
CHECK((etl::is_copy_assignable<MoveableCopyable>::value) == (std::is_copy_assignable<MoveableCopyable>::value));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_is_move_assignable)
|
||||
{
|
||||
#if ETL_USING_CPP17
|
||||
CHECK((etl::is_move_assignable_v<Copyable>) == (std::is_move_assignable_v<Copyable>));
|
||||
CHECK((etl::is_move_assignable_v<Moveable>) == (std::is_move_assignable_v<Moveable>));
|
||||
CHECK((etl::is_move_assignable_v<MoveableCopyable>) == (std::is_move_assignable_v<MoveableCopyable>));
|
||||
#else
|
||||
CHECK((etl::is_move_assignable<Copyable>::value) == (std::is_move_assignable<Copyable>::value));
|
||||
CHECK((etl::is_move_assignable<Moveable>::value) == (std::is_move_assignable<Moveable>::value));
|
||||
CHECK((etl::is_move_assignable<MoveableCopyable>::value) == (std::is_move_assignable<MoveableCopyable>::value));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_is_trivially_constructible)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user