@@ -322,7 +322,7 @@ struct static_type_mapping<BoxedValue<T>>
322
322
template <typename T> using static_julia_type = typename static_type_mapping<T>::type;
323
323
324
324
// Store a data type pointer, ensuring GC safety
325
- struct CachedDatatype
325
+ struct JLCXX_API CachedDatatype
326
326
{
327
327
explicit CachedDatatype () : m_dt(nullptr ) {}
328
328
explicit CachedDatatype (jl_datatype_t * dt, bool protect = true )
@@ -348,112 +348,64 @@ struct CachedDatatype
348
348
jl_datatype_t * m_dt = nullptr ;
349
349
};
350
350
351
- // Work around the fact that references aren't part of the typeid result
352
- using type_hash_t = std::pair<std::type_index, std::size_t >;
353
351
354
- } // namespace jlcxx
352
+ # ifdef JLCXX_USE_TYPE_MAP
355
353
356
- namespace std {
357
-
358
- // Hash implementation from https://en.cppreference.com/w/cpp/utility/hash
359
- template <>
360
- struct hash <jlcxx::type_hash_t >
361
- {
362
- std::size_t operator ()(const jlcxx::type_hash_t & h) const noexcept
363
- {
364
- std::size_t h1 = std::hash<std::type_index>{}(h.first );
365
- std::size_t h2 = std::hash<std::size_t >{}(h.second );
366
- return h1 ^ (h2 << 1 );
367
- }
368
- };
369
-
370
- }
371
-
372
- namespace jlcxx
373
- {
374
-
375
- namespace detail
376
- {
354
+ JLCXX_API CachedDatatype& jlcxx_type (std::type_index idx);
355
+ JLCXX_API CachedDatatype& jlcxx_reftype (std::type_index idx);
356
+ JLCXX_API CachedDatatype& jlcxx_constreftype (std::type_index idx);
377
357
378
358
template <typename T>
379
- struct TypeHash
359
+ struct HashedCache
380
360
{
381
- static inline type_hash_t value ()
361
+ static inline CachedDatatype& value ()
382
362
{
383
- return std::make_pair ( std::type_index ( typeid (T)), std::size_t ( 0 ));
363
+ return jlcxx_type ( typeid (T));
384
364
}
385
365
};
386
366
387
367
template <typename T>
388
- struct TypeHash <T&>
368
+ struct HashedCache <T&>
389
369
{
390
- static inline type_hash_t value ()
370
+ static inline CachedDatatype& value ()
391
371
{
392
- return std::make_pair ( std::type_index ( typeid (T)), std::size_t ( 1 ));
372
+ return jlcxx_reftype ( typeid (T));
393
373
}
394
374
};
395
375
396
376
template <typename T>
397
- struct TypeHash <const T&>
377
+ struct HashedCache <const T&>
398
378
{
399
- static inline type_hash_t value ()
379
+ static inline CachedDatatype& value ()
400
380
{
401
- return std::make_pair ( std::type_index ( typeid (T)), std::size_t ( 2 ));
381
+ return jlcxx_constreftype ( typeid (T));
402
382
}
403
383
};
404
384
405
- }
385
+ # endif
406
386
407
- template <typename T >
408
- inline type_hash_t type_hash ()
387
+ template <typename CppT >
388
+ CachedDatatype& stored_type ()
409
389
{
410
- return detail::TypeHash<T>::value ();
390
+ #ifdef JLCXX_USE_TYPE_MAP
391
+ return HashedCache<CppT>::value ();
392
+ #else
393
+ static CachedDatatype m_dt;
394
+ return m_dt;
395
+ #endif
411
396
}
412
397
413
- JLCXX_API std::unordered_map<type_hash_t , CachedDatatype>& jlcxx_type_map ();
414
-
415
- // / Store the Julia datatype linked to SourceT
416
- template <typename SourceT>
417
- class JuliaTypeCache
418
- {
419
- public:
420
-
421
- static inline jl_datatype_t * julia_type ()
422
- {
423
- const auto result = jlcxx_type_map ().find (type_hash<SourceT>());
424
- if (result == jlcxx_type_map ().end ())
425
- {
426
- throw std::runtime_error (" Type " + std::string (typeid (SourceT).name ()) + " has no Julia wrapper" );
427
- }
428
- return result->second .get_dt ();
429
- }
430
-
431
- static inline void set_julia_type (jl_datatype_t * dt, bool protect = true )
432
- {
433
- type_hash_t new_hash = type_hash<SourceT>();
434
- const auto [inserted_it, insert_success] = jlcxx_type_map ().insert (std::make_pair (new_hash, CachedDatatype (dt, protect)));
435
- if (!insert_success)
436
- {
437
- type_hash_t old_hash = inserted_it->first ;
438
- std::cout << " Warning: Type " << new_hash.first .name () << " already had a mapped type set as "
439
- << julia_type_name (inserted_it->second .get_dt ()) << " and const-ref indicator " << old_hash.second << " and C++ type name " << old_hash.first .name ()
440
- << " . Hash comparison: old(" << old_hash.first .hash_code () << " ," << old_hash.second << " ) == new(" << old_hash.first .hash_code () << " ," << old_hash.second << " ) == "
441
- << std::boolalpha << (old_hash == new_hash) << std::endl;
442
- return ;
443
- }
444
- }
445
-
446
- static inline bool has_julia_type ()
447
- {
448
- const std::size_t nb_hits = jlcxx_type_map ().count (type_hash<SourceT>());
449
- return nb_hits != 0 ;
450
- }
451
- };
452
-
453
398
template <typename T>
454
399
void set_julia_type (jl_datatype_t * dt, bool protect = true )
455
400
{
456
- JuliaTypeCache<typename std::remove_const<T>::type>::set_julia_type (dt, protect);
401
+ using nonconst_t = typename std::remove_const<T>::type;
402
+ CachedDatatype& cache = stored_type<nonconst_t >();
403
+ if (cache.get_dt () != nullptr )
404
+ {
405
+ std::cout << " Warning: Type " << typeid (T).name () << " already had a mapped type set as " << julia_type_name (cache.get_dt ()) << std::endl;
406
+ return ;
407
+ }
408
+ cache.set_dt (dt, protect);
457
409
}
458
410
459
411
// / Store the Julia datatype linked to SourceT
@@ -473,7 +425,11 @@ template<typename T>
473
425
inline jl_datatype_t * julia_type ()
474
426
{
475
427
using nonconst_t = typename std::remove_const<T>::type;
476
- static jl_datatype_t * dt = JuliaTypeCache<nonconst_t >::julia_type ();
428
+ jl_datatype_t * dt = stored_type<nonconst_t >().get_dt ();
429
+ if (dt == nullptr )
430
+ {
431
+ throw std::runtime_error (" Type " + std::string (typeid (nonconst_t ).name ()) + " has no Julia wrapper" );
432
+ }
477
433
return dt;
478
434
}
479
435
@@ -482,7 +438,7 @@ template <typename T>
482
438
bool has_julia_type ()
483
439
{
484
440
using nonconst_t = typename std::remove_const<T>::type;
485
- return JuliaTypeCache <nonconst_t >:: has_julia_type () ;
441
+ return stored_type <nonconst_t >(). get_dt () != nullptr ;
486
442
}
487
443
488
444
// / Create the julia type associated with the given C++ type
0 commit comments