@@ -119,6 +119,20 @@ namespace xt
119
119
using type = T;
120
120
};
121
121
122
+ /* **************************************
123
+ * is_specialization_of implementation *
124
+ ***************************************/
125
+
126
+ template <template <class ...> class TT , class T >
127
+ struct is_specialization_of : std::false_type
128
+ {
129
+ };
130
+
131
+ template <template <class ...> class TT , class ... Ts>
132
+ struct is_specialization_of <TT, TT<Ts...>> : std::true_type
133
+ {
134
+ };
135
+
122
136
/* ******************************
123
137
* remove_class implementation *
124
138
*******************************/
@@ -860,6 +874,139 @@ namespace xt
860
874
{
861
875
};
862
876
877
+ /* ************************************
878
+ * overlapping_memory_checker_traits *
879
+ *************************************/
880
+
881
+ template <class T , class Enable = void >
882
+ struct has_memory_address : std::false_type
883
+ {
884
+ };
885
+
886
+ template <class T >
887
+ struct has_memory_address <T, void_t <decltype(std::addressof(*std::declval<T>().begin()))>> : std::true_type
888
+ {
889
+ };
890
+
891
+ struct memory_range
892
+ {
893
+ // Checking pointer overlap is more correct in integer values,
894
+ // for more explanation check https://devblogs.microsoft.com/oldnewthing/20170927-00/?p=97095
895
+ const uintptr_t m_first = 0 ;
896
+ const uintptr_t m_last = 0 ;
897
+
898
+ explicit memory_range () = default;
899
+
900
+ template <class T >
901
+ explicit memory_range (T* first, T* last)
902
+ : m_first(reinterpret_cast <uintptr_t >(last < first ? last : first))
903
+ , m_last(reinterpret_cast <uintptr_t >(last < first ? first : last))
904
+ {
905
+ }
906
+
907
+ template <class T >
908
+ bool overlaps (T* first, T* last) const
909
+ {
910
+ if (first <= last)
911
+ {
912
+ return reinterpret_cast <uintptr_t >(first) <= m_last
913
+ && reinterpret_cast <uintptr_t >(last) >= m_first;
914
+ }
915
+ else
916
+ {
917
+ return reinterpret_cast <uintptr_t >(last) <= m_last
918
+ && reinterpret_cast <uintptr_t >(first) >= m_first;
919
+ }
920
+ }
921
+ };
922
+
923
+ template <class E , class Enable = void >
924
+ struct overlapping_memory_checker_traits
925
+ {
926
+ static bool check_overlap (const E&, const memory_range&)
927
+ {
928
+ return true ;
929
+ }
930
+ };
931
+
932
+ template <class E >
933
+ struct overlapping_memory_checker_traits <E, std::enable_if_t <has_memory_address<E>::value>>
934
+ {
935
+ static bool check_overlap (const E& expr, const memory_range& dst_range)
936
+ {
937
+ if (expr.size () == 0 )
938
+ {
939
+ return false ;
940
+ }
941
+ else
942
+ {
943
+ return dst_range.overlaps (std::addressof (*expr.begin ()), std::addressof (*expr.rbegin ()));
944
+ }
945
+ }
946
+ };
947
+
948
+ struct overlapping_memory_checker_base
949
+ {
950
+ memory_range m_dst_range;
951
+
952
+ explicit overlapping_memory_checker_base () = default;
953
+
954
+ explicit overlapping_memory_checker_base (memory_range dst_memory_range)
955
+ : m_dst_range(std::move(dst_memory_range))
956
+ {
957
+ }
958
+
959
+ template <class E >
960
+ bool check_overlap (const E& expr) const
961
+ {
962
+ if (!m_dst_range.m_first || !m_dst_range.m_last )
963
+ {
964
+ return false ;
965
+ }
966
+ else
967
+ {
968
+ return overlapping_memory_checker_traits<E>::check_overlap (expr, m_dst_range);
969
+ }
970
+ }
971
+ };
972
+
973
+ template <class Dst , class Enable = void >
974
+ struct overlapping_memory_checker : overlapping_memory_checker_base
975
+ {
976
+ explicit overlapping_memory_checker (const Dst&)
977
+ : overlapping_memory_checker_base()
978
+ {
979
+ }
980
+ };
981
+
982
+ template <class Dst >
983
+ struct overlapping_memory_checker <Dst, std::enable_if_t <has_memory_address<Dst>::value>>
984
+ : overlapping_memory_checker_base
985
+ {
986
+ explicit overlapping_memory_checker (const Dst& aDst)
987
+ : overlapping_memory_checker_base(
988
+ [&]()
989
+ {
990
+ if (aDst.size () == 0 )
991
+ {
992
+ return memory_range ();
993
+ }
994
+ else
995
+ {
996
+ return memory_range (std::addressof (*aDst.begin ()), std::addressof (*aDst.rbegin ()));
997
+ }
998
+ }()
999
+ )
1000
+ {
1001
+ }
1002
+ };
1003
+
1004
+ template <class Dst >
1005
+ auto make_overlapping_memory_checker (const Dst& a_dst)
1006
+ {
1007
+ return overlapping_memory_checker<Dst>(a_dst);
1008
+ }
1009
+
863
1010
/* *******************
864
1011
* rebind_container *
865
1012
********************/
0 commit comments