@@ -341,6 +341,19 @@ class String
341341 return !isEqual (other.c_str ());
342342 }
343343
344+ // Assignment operators for automatic conversion
345+ String& operator =(const std::string& other)
346+ {
347+ assign (*this , other);
348+ return *this ;
349+ }
350+
351+ String& operator =(const char * other)
352+ {
353+ assign (*this , other);
354+ return *this ;
355+ }
356+
344357 // friend class BlobBuilder;
345358
346359 // Friend declarations for new Builder API
@@ -424,6 +437,14 @@ template <typename T> class Array
424437
425438 ZMEYA_NODISCARD bool empty () const noexcept { return size () == 0 ; }
426439
440+ // Assignment operators for automatic conversion
441+ template <typename F>
442+ Array<T>& operator =(const std::vector<F>& other)
443+ {
444+ assign (*this , other);
445+ return *this ;
446+ }
447+
427448 // friend class BlobBuilder;
428449
429450 // Friend declarations for new Builder API
@@ -539,6 +560,15 @@ template <typename Key> class HashSet
539560 }
540561
541562 ZMEYA_NODISCARD bool contains (const Key& key) const noexcept { return containsImpl<Key, HashKeyAdapterGeneric<Key>>(key); }
563+
564+ // Assignment operators for automatic conversion
565+ template <typename F>
566+ HashSet<Key>& operator =(const std::unordered_set<F>& other)
567+ {
568+ assign (*this , other);
569+ return *this ;
570+ }
571+
542572 // friend class BlobBuilder;
543573
544574 // Friend declarations for new Builder API
@@ -703,6 +733,14 @@ template <typename Key, typename Value> class HashMap
703733 return valueIfNotFound;
704734 }
705735
736+ // Assignment operators for automatic conversion
737+ template <typename FK, typename FV>
738+ HashMap<Key, Value>& operator =(const std::unordered_map<FK, FV>& other)
739+ {
740+ assign (*this , other);
741+ return *this ;
742+ }
743+
706744 // friend class BlobBuilder;
707745
708746 // Friend declarations for new Builder API
@@ -2014,30 +2052,9 @@ template <typename T, typename F> void assign(Array<T>& _to, const std::vector<F
20142052
20152053 for (size_t i = 0 ; i < from.size (); ++i)
20162054 {
2017- // deep-copy elements
2018- // TODO: add range check for offset to make sure it within the valid range (goffset_t)
2055+ // deep-copy elements using the universal deep_copy function
20192056 zm::goffset_t elementOffset = zm::goffset_t (arrayDataOffset + i * sizeOfT);
2020-
2021- // Use placement constructor and then assign
2022- T* element = reinterpret_cast <T*>(builder->get_ptr_unsafe_to_store (elementOffset));
2023- BuilderBase::placementCtor<T>(element);
2024-
2025- // For fundamental types, direct assignment
2026- if constexpr (std::is_fundamental_v<F> && std::is_fundamental_v<T>) {
2027- *element = static_cast <T>(from[i]);
2028- }
2029- // For string conversion
2030- else if constexpr (std::is_same_v<F, std::string> && std::is_same_v<T, String>) {
2031- assign (*element, from[i]);
2032- }
2033- // For vector to array conversion (nested arrays)
2034- else if constexpr (std::is_same_v<std::decay_t <F>, std::vector<typename std::decay_t <F>::value_type, typename std::decay_t <F>::allocator_type>>) {
2035- assign (*element, from[i]);
2036- }
2037- // For other complex types, this shouldn't happen in practice
2038- else {
2039- static_assert (sizeof (F) == 0 , " Unsupported type conversion in deep_copy" );
2040- }
2057+ deep_copy<F, T>(from[i], elementOffset);
20412058 }
20422059}
20432060
@@ -2114,14 +2131,8 @@ template <typename Key, typename F> void assign(HashSet<Key>& _to, const std::un
21142131 Key* element = &items[bucket.endIndex ];
21152132 BuilderBase::placementCtor<Key>(element);
21162133
2117- // Assign the item using the same logic as Array assign
2118- if constexpr (std::is_fundamental_v<F> && std::is_fundamental_v<Key>) {
2119- *element = static_cast <Key>(item);
2120- } else if constexpr (std::is_same_v<F, std::string> && std::is_same_v<Key, String>) {
2121- assign (*element, item);
2122- } else {
2123- assign (*element, item);
2124- }
2134+ // Assign the item using operator= (automatic conversion)
2135+ *element = item;
21252136
21262137 bucket.endIndex ++;
21272138 }
@@ -2254,23 +2265,9 @@ void assign(HashMap<Key, Value>& _to, const std::unordered_map<FK, FV>& from)
22542265 BuilderBase::placementCtor<Key>(mutableKey);
22552266 BuilderBase::placementCtor<Value>(&element->second );
22562267
2257- // Assign key
2258- if constexpr (std::is_fundamental_v<FK> && std::is_fundamental_v<Key>) {
2259- *mutableKey = static_cast <Key>(key);
2260- } else if constexpr (std::is_same_v<FK, std::string> && std::is_same_v<Key, String>) {
2261- assign (*mutableKey, key);
2262- } else {
2263- assign (*mutableKey, key);
2264- }
2265-
2266- // Assign value
2267- if constexpr (std::is_fundamental_v<FV> && std::is_fundamental_v<Value>) {
2268- element->second = static_cast <Value>(value);
2269- } else if constexpr (std::is_same_v<FV, std::string> && std::is_same_v<Value, String>) {
2270- assign (element->second , value);
2271- } else {
2272- assign (element->second , value);
2273- }
2268+ // Assign key and value using operator= (automatic conversion)
2269+ *mutableKey = key;
2270+ element->second = value;
22742271
22752272 bucket.endIndex ++;
22762273 }
@@ -2322,67 +2319,14 @@ void assign(HashMap<Key, Value>& _to, const std::unordered_map<FK, FV>& from)
23222319
23232320// Deep-copy adapter implementations
23242321
2325- // Generic copy for fundamental types only (int, float, etc.)
2326- template <typename F, typename T>
2327- std::enable_if_t <std::is_fundamental_v<std::decay_t <F>> && std::is_fundamental_v<std::decay_t <T>> && std::is_convertible_v<F, T>>
2328- deep_copy (const F& from, zm::goffset_t to_ofs)
2322+ // Universal deep_copy - works for all types thanks to operator= overloads
2323+ template <typename F, typename T> void deep_copy (const F& from, zm::goffset_t to_ofs)
23292324{
23302325 BuilderBase* builder = detail::get_global_builder ();
23312326 ZMEYA_ASSERT (builder != nullptr );
23322327 T* p_to = reinterpret_cast <T*>(builder->get_ptr_unsafe_to_store (to_ofs));
2333- *p_to = static_cast <T>(from);
2334- }
2335-
2336- // Specialized overloads for std::* -> zm::* conversions
2337- inline void deep_copy (const std::string& from, zm::goffset_t to_ofs)
2338- {
2339- BuilderBase* builder = detail::get_global_builder ();
2340- ZMEYA_ASSERT (builder != nullptr );
2341- String* p_to = reinterpret_cast <String*>(builder->get_ptr_unsafe_to_store (to_ofs));
2342- assign (*p_to, from);
2343- }
2344-
2345- inline void deep_copy (const char * from, zm::goffset_t to_ofs)
2346- {
2347- BuilderBase* builder = detail::get_global_builder ();
2348- ZMEYA_ASSERT (builder != nullptr );
2349- String* p_to = reinterpret_cast <String*>(builder->get_ptr_unsafe_to_store (to_ofs));
2350- assign (*p_to, from);
2351- }
2352-
2353- template <typename F, typename T> void deep_copy (const std::vector<F>& from, zm::goffset_t to_ofs)
2354- {
2355- BuilderBase* builder = detail::get_global_builder ();
2356- ZMEYA_ASSERT (builder != nullptr );
2357- Array<T>* p_to = reinterpret_cast <Array<T>*>(builder->get_ptr_unsafe_to_store (to_ofs));
2358- assign (*p_to, from);
2359- }
2360-
2361- template <typename F, typename Key> void deep_copy (const std::unordered_set<F>& from, zm::goffset_t to_ofs)
2362- {
2363- BuilderBase* builder = detail::get_global_builder ();
2364- ZMEYA_ASSERT (builder != nullptr );
2365- HashSet<Key>* p_to = reinterpret_cast <HashSet<Key>*>(builder->get_ptr_unsafe_to_store (to_ofs));
2366- assign (*p_to, from);
2367- }
2368-
2369- template <typename FK, typename FV, typename Key, typename Value>
2370- void deep_copy (const std::unordered_map<FK, FV>& from, zm::goffset_t to_ofs)
2371- {
2372- BuilderBase* builder = detail::get_global_builder ();
2373- ZMEYA_ASSERT (builder != nullptr );
2374- HashMap<Key, Value>* p_to = reinterpret_cast <HashMap<Key, Value>*>(builder->get_ptr_unsafe_to_store (to_ofs));
2375- assign (*p_to, from);
2376- }
2377-
2378- // Pair conversions
2379- template <typename F1, typename F2, typename T1, typename T2> void deep_copy (const Pair<F1, F2>& from, zm::goffset_t to_ofs)
2380- {
2381- BuilderBase* builder = detail::get_global_builder ();
2382- ZMEYA_ASSERT (builder != nullptr );
2383- Pair<T1, T2>* p_to = reinterpret_cast <Pair<T1, T2>*>(builder->get_ptr_unsafe_to_store (to_ofs));
2384- deep_copy (from.first , builder->get_global_offset (&p_to->first ));
2385- deep_copy (from.second , builder->get_global_offset (&p_to->second ));
2328+ BuilderBase::placementCtor<T>(p_to);
2329+ *p_to = from; // This will call the appropriate operator= automatically!
23862330}
23872331
23882332/*
0 commit comments