Skip to content

Commit 5914b81

Browse files
committed
mbed_atomic.h: Improve template type deduction
Avoid template ambiguities using type_identity_t. Previously the compiler would be unable to figure out whether uint8_t x; core_util_atomic_store(&x, 0); should invoke core_util_atomic_store<uint8_t>, matching the pointer type, or core_util_atomic_store<int>, matching the value, leading to an ambiguity error. Templates now select only on the type of the atomic pointer parameter.
1 parent 393ca3e commit 5914b81

File tree

1 file changed

+37
-36
lines changed

1 file changed

+37
-36
lines changed

platform/mbed_atomic.h

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -880,84 +880,85 @@ MBED_FORCEINLINE uint64_t core_util_atomic_fetch_xor_explicit_u64(volatile uint6
880880
#ifdef __cplusplus
881881
} // extern "C"
882882

883+
#include "mbed_cxxsupport.h"
884+
883885
// For each operation, two overloaded templates:
884886
// * one for non-pointer types, which has implementations based on the
885887
// u8/u16/u32/u64/s8/s16/s32/s64/bool functions above. No base implementation.
886888
// * one for any pointer type, generically implemented based on ptr function above.
887889
//
888890
// Templates use standard C/C++ naming - old incr/decr/cas forms are not provided.
889891
//
890-
// Note that C++ template selection somewhat inhibits the ease of use of these templates.
891-
// Ambiguities arise with setting pointers to NULL, or adding constants to integers.
892-
// It may be necessary to cast the argument or desired value to the correct type, or
893-
// explictly specify the type - eg core_util_atomic_store<FileHandle>(&fh, NULL) or
894-
// core_util_atomic_store(&val, (uint8_t)1).
895-
// A proper mbed::Atomic<T> class would solve the issue.
892+
// The `type_identity_t<T>` used here means "same type as T", blocking template
893+
// argument deduction. It forces type selection based on the type of the actual pointer
894+
// to the atomic. If just `T` was used, the following would be ambiguous:
895+
// core_util_atomic_store(&my_uint8_t, 1) - it wouldn't be able to select between T
896+
// being uint8_t and int.
896897

897898
/** \copydoc core_util_atomic_load_u8 */
898899
template<typename T> T core_util_atomic_load(const volatile T *valuePtr) noexcept;
899900
/** \copydoc core_util_atomic_load_u8 */
900901
template<typename T> T core_util_atomic_load(const T *valuePtr) noexcept;
901902
/** \copydoc core_util_atomic_store_u8 */
902-
template<typename T> void core_util_atomic_store(volatile T *valuePtr, T desiredValue) noexcept;
903+
template<typename T> void core_util_atomic_store(volatile T *valuePtr, mbed::type_identity_t<T> desiredValue) noexcept;
903904
/** \copydoc core_util_atomic_store_u8 */
904-
template<typename T> void core_util_atomic_store(T *valuePtr, T desiredValue) noexcept;
905+
template<typename T> void core_util_atomic_store(T *valuePtr, mbed::type_identity_t<T> desiredValue) noexcept;
905906
/** \copydoc core_util_atomic_exchange_u8 */
906-
template<typename T> T core_util_atomic_exchange(volatile T *ptr, T desiredValue) noexcept;
907+
template<typename T> T core_util_atomic_exchange(volatile T *ptr, mbed::type_identity_t<T> desiredValue) noexcept;
907908
/** \copydoc core_util_atomic_cas_u8 */
908-
template<typename T> bool core_util_atomic_compare_exchange_strong(volatile T *ptr, T *expectedCurrentValue, T desiredValue) noexcept;
909+
template<typename T> bool core_util_atomic_compare_exchange_strong(volatile T *ptr, mbed::type_identity_t<T> *expectedCurrentValue, mbed::type_identity_t<T> desiredValue) noexcept;
909910
/** \copydoc core_util_atomic_compare_exchange_weak_u8 */
910-
template<typename T> bool core_util_atomic_compare_exchange_weak(volatile T *ptr, T *expectedCurrentValue, T desiredValue) noexcept;
911+
template<typename T> bool core_util_atomic_compare_exchange_weak(volatile T *ptr, mbed::type_identity_t<T> *expectedCurrentValue, mbed::type_identity_t<T> desiredValue) noexcept;
911912
/** \copydoc core_util_fetch_add_u8 */
912-
template<typename T> T core_util_atomic_fetch_add(volatile T *valuePtr, T arg) noexcept;
913+
template<typename T> T core_util_atomic_fetch_add(volatile T *valuePtr, mbed::type_identity_t<T> arg) noexcept;
913914
/** \copydoc core_util_fetch_sub_u8 */
914-
template<typename T> T core_util_atomic_fetch_sub(volatile T *valuePtr, T arg) noexcept;
915+
template<typename T> T core_util_atomic_fetch_sub(volatile T *valuePtr, mbed::type_identity_t<T> arg) noexcept;
915916
/** \copydoc core_util_fetch_and_u8 */
916-
template<typename T> T core_util_atomic_fetch_and(volatile T *valuePtr, T arg) noexcept;
917+
template<typename T> T core_util_atomic_fetch_and(volatile T *valuePtr, mbed::type_identity_t<T> arg) noexcept;
917918
/** \copydoc core_util_fetch_or_u8 */
918-
template<typename T> T core_util_atomic_fetch_or(volatile T *valuePtr, T arg) noexcept;
919+
template<typename T> T core_util_atomic_fetch_or(volatile T *valuePtr, mbed::type_identity_t<T> arg) noexcept;
919920
/** \copydoc core_util_fetch_xor_u8 */
920-
template<typename T> T core_util_atomic_fetch_xor(volatile T *valuePtr, T arg) noexcept;
921+
template<typename T> T core_util_atomic_fetch_xor(volatile T *valuePtr, mbed::type_identity_t<T> arg) noexcept;
921922

922923
/** \copydoc core_util_atomic_load_explicit_u8 */
923924
template<typename T> T core_util_atomic_load_explicit(const volatile T *valuePtr, mbed_memory_order order) noexcept;
924925
/** \copydoc core_util_atomic_load_explicit_u8 */
925926
template<typename T> T core_util_atomic_load_explicit(const T *valuePtr, mbed_memory_order order) noexcept;
926927
/** \copydoc core_util_atomic_store_explicit_u8 */
927-
template<typename T> void core_util_atomic_store_explicit(volatile T *valuePtr, T desiredValue, mbed_memory_order order) noexcept;
928+
template<typename T> void core_util_atomic_store_explicit(volatile T *valuePtr, mbed::type_identity_t<T> desiredValue, mbed_memory_order order) noexcept;
928929
/** \copydoc core_util_atomic_store_explicit_u8 */
929-
template<typename T> void core_util_atomic_store_explicit(T *valuePtr, T desiredValue, mbed_memory_order order) noexcept;
930+
template<typename T> void core_util_atomic_store_explicit(T *valuePtr, mbed::type_identity_t<T> desiredValue, mbed_memory_order order) noexcept;
930931
/** \copydoc core_util_atomic_exchange_explicit_u8 */
931-
template<typename T> T core_util_atomic_exchange_explicit(volatile T *ptr, T desiredValue, mbed_memory_order order) noexcept;
932+
template<typename T> T core_util_atomic_exchange_explicit(volatile T *ptr, mbed::type_identity_t<T> desiredValue, mbed_memory_order order) noexcept;
932933
/** \copydoc core_util_atomic_cas_explicit_u8 */
933-
template<typename T> bool core_util_atomic_compare_exchange_strong_explicit(volatile T *ptr, T *expectedCurrentValue, T desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
934+
template<typename T> bool core_util_atomic_compare_exchange_strong_explicit(volatile T *ptr, mbed::type_identity_t<T> *expectedCurrentValue, mbed::type_identity_t<T> desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
934935
/** \copydoc core_util_atomic_compare_exchange_weak_explicit_u8 */
935-
template<typename T> bool core_util_atomic_compare_exchange_weak_explicit(volatile T *ptr, T *expectedCurrentValue, T desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
936+
template<typename T> bool core_util_atomic_compare_exchange_weak_explicit(volatile T *ptr, mbed::type_identity_t<T> *expectedCurrentValue, mbed::type_identity_t<T> desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
936937
/** \copydoc core_util_fetch_add_explicit_u8 */
937-
template<typename T> T core_util_atomic_fetch_add_explicit(volatile T *valuePtr, T arg, mbed_memory_order order) noexcept;
938+
template<typename T> T core_util_atomic_fetch_add_explicit(volatile T *valuePtr, mbed::type_identity_t<T> arg, mbed_memory_order order) noexcept;
938939
/** \copydoc core_util_fetch_sub_explicit_u8 */
939-
template<typename T> T core_util_atomic_fetch_sub_explicit(volatile T *valuePtr, T arg, mbed_memory_order order) noexcept;
940+
template<typename T> T core_util_atomic_fetch_sub_explicit(volatile T *valuePtr, mbed::type_identity_t<T> arg, mbed_memory_order order) noexcept;
940941
/** \copydoc core_util_fetch_and_explicit_u8 */
941-
template<typename T> T core_util_atomic_fetch_and_explicit(volatile T *valuePtr, T arg, mbed_memory_order order) noexcept;
942+
template<typename T> T core_util_atomic_fetch_and_explicit(volatile T *valuePtr, mbed::type_identity_t<T> arg, mbed_memory_order order) noexcept;
942943
/** \copydoc core_util_fetch_or_explicit_u8 */
943-
template<typename T> T core_util_atomic_fetch_or_explicit(volatile T *valuePtr, T arg, mbed_memory_order order) noexcept;
944+
template<typename T> T core_util_atomic_fetch_or_explicit(volatile T *valuePtr, mbed::type_identity_t<T> arg, mbed_memory_order order) noexcept;
944945
/** \copydoc core_util_fetch_xor_explicit_u8 */
945-
template<typename T> T core_util_atomic_fetch_xor_explicit(volatile T *valuePtr, T arg, mbed_memory_order order) noexcept;
946+
template<typename T> T core_util_atomic_fetch_xor_explicit(volatile T *valuePtr, mbed::type_identity_t<T> arg, mbed_memory_order order) noexcept;
946947

947948
/** \copydoc core_util_atomic_load_ptr */
948949
template<typename T> inline T *core_util_atomic_load(T *const volatile *valuePtr) noexcept;
949950
/** \copydoc core_util_atomic_load_ptr */
950951
template<typename T> inline T *core_util_atomic_load(T *const *valuePtr) noexcept;
951952
/** \copydoc core_util_atomic_store_ptr */
952-
template<typename T> inline void core_util_atomic_store(T *volatile *valuePtr, T *desiredValue) noexcept;
953+
template<typename T> inline void core_util_atomic_store(T *volatile *valuePtr, mbed::type_identity_t<T> *desiredValue) noexcept;
953954
/** \copydoc core_util_atomic_store_ptr */
954-
template<typename T> inline void core_util_atomic_store(T **valuePtr, T *desiredValue) noexcept;
955+
template<typename T> inline void core_util_atomic_store(T **valuePtr, mbed::type_identity_t<T> *desiredValue) noexcept;
955956
/** \copydoc core_util_atomic_exchange_ptr */
956-
template<typename T> inline T *core_util_atomic_exchange(T *volatile *valuePtr, T *desiredValue) noexcept;
957+
template<typename T> inline T *core_util_atomic_exchange(T *volatile *valuePtr, mbed::type_identity_t<T> *desiredValue) noexcept;
957958
/** \copydoc core_util_atomic_cas_ptr */
958-
template<typename T> inline bool core_util_atomic_compare_exchange_strong(T *volatile *ptr, T **expectedCurrentValue, T *desiredValue) noexcept;
959+
template<typename T> inline bool core_util_atomic_compare_exchange_strong(T *volatile *ptr, mbed::type_identity_t<T> **expectedCurrentValue, mbed::type_identity_t<T> *desiredValue) noexcept;
959960
/** \copydoc core_util_atomic_compare_exchange_weak_ptr */
960-
template<typename T> inline bool core_util_atomic_compare_exchange_weak(T *volatile *ptr, T **expectedCurrentValue, T *desiredValue) noexcept;
961+
template<typename T> inline bool core_util_atomic_compare_exchange_weak(T *volatile *ptr, mbed::type_identity_t<T> **expectedCurrentValue, mbed::type_identity_t<T> *desiredValue) noexcept;
961962
/** \copydoc core_util_fetch_add_ptr */
962963
template<typename T> inline T *core_util_atomic_fetch_add(T *volatile *valuePtr, ptrdiff_t arg) noexcept;
963964
/** \copydoc core_util_fetch_sub_ptr */
@@ -968,15 +969,15 @@ template<typename T> inline T *core_util_atomic_load_explicit(T *const volatile
968969
/** \copydoc core_util_atomic_load_explicit_ptr */
969970
template<typename T> inline T *core_util_atomic_load_explicit(T *const *valuePtr, mbed_memory_order order) noexcept;
970971
/** \copydoc core_util_atomic_store_explicit_ptr */
971-
template<typename T> inline void core_util_atomic_store_explicit(T *volatile *valuePtr, T *desiredValue, mbed_memory_order order) noexcept;
972+
template<typename T> inline void core_util_atomic_store_explicit(T *volatile *valuePtr, mbed::type_identity_t<T> *desiredValue, mbed_memory_order order) noexcept;
972973
/** \copydoc core_util_atomic_store_explicit_ptr */
973-
template<typename T> inline void core_util_atomic_store_explicit(T **valuePtr, T *desiredValue, mbed_memory_order order) noexcept;
974+
template<typename T> inline void core_util_atomic_store_explicit(T **valuePtr, mbed::type_identity_t<T> *desiredValue, mbed_memory_order order) noexcept;
974975
/** \copydoc core_util_atomic_exchange_explicit_ptr */
975-
template<typename T> inline T *core_util_atomic_exchange_explicit(T *volatile *valuePtr, T *desiredValue, mbed_memory_order order) noexcept;
976+
template<typename T> inline T *core_util_atomic_exchange_explicit(T *volatile *valuePtr, mbed::type_identity_t<T> *desiredValue, mbed_memory_order order) noexcept;
976977
/** \copydoc core_util_atomic_cas_explicit_ptr */
977-
template<typename T> inline bool core_util_atomic_compare_exchange_strong_explicit(T *volatile *ptr, T **expectedCurrentValue, T *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
978+
template<typename T> inline bool core_util_atomic_compare_exchange_strong_explicit(T *volatile *ptr, mbed::type_identity_t<T> **expectedCurrentValue, mbed::type_identity_t<T> *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
978979
/** \copydoc core_util_atomic_compare_exchange_weak_explicit_ptr */
979-
template<typename T> inline bool core_util_atomic_compare_exchange_weak_explicit(T *volatile *ptr, T **expectedCurrentValue, T *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
980+
template<typename T> inline bool core_util_atomic_compare_exchange_weak_explicit(T *volatile *ptr, mbed::type_identity_t<T> **expectedCurrentValue, mbed::type_identity_t<T> *desiredValue, mbed_memory_order success, mbed_memory_order failure) noexcept;
980981
/** \copydoc core_util_fetch_add_explicit_ptr */
981982
template<typename T> inline T *core_util_atomic_fetch_add_explicit(T *volatile *valuePtr, ptrdiff_t arg, mbed_memory_order order) noexcept;
982983
/** \copydoc core_util_fetch_sub_explicit_ptr */

0 commit comments

Comments
 (0)