Skip to content

Commit 92a1953

Browse files
committed
Allow using tuples in STL containers
For issue JuliaInterop/CxxWrap.jl#469
1 parent b7844ae commit 92a1953

File tree

2 files changed

+92
-74
lines changed

2 files changed

+92
-74
lines changed

examples/containers.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "jlcxx/tuple.hpp"
66
#include "jlcxx/const_array.hpp"
77
#include "jlcxx/functions.hpp"
8+
#include "jlcxx/stl.hpp"
89

910
const double* const_vector()
1011
{
@@ -57,6 +58,14 @@ std::vector<double> read_array_tuple(std::tuple<jlcxx::ArrayRef<double>, jlcxx::
5758
return result;
5859
}
5960

61+
std::vector<std::tuple<double,double>> make_tuple_vector()
62+
{
63+
std::vector<std::tuple<double,double>> result;
64+
result.push_back(std::make_tuple(1.0, 2.0));
65+
result.push_back(std::make_tuple(3.0, 4.0));
66+
return result;
67+
}
68+
6069
JLCXX_MODULE define_julia_module(jlcxx::Module& containers)
6170
{
6271
using namespace jlcxx;
@@ -123,4 +132,5 @@ JLCXX_MODULE define_julia_module(jlcxx::Module& containers)
123132
containers.method("copy_tuple", &copy_tuple);
124133
containers.method("make_array_tuple", &make_array_tuple);
125134
containers.method("read_array_tuple", &read_array_tuple);
135+
containers.method("make_tuple_vector", &make_tuple_vector);
126136
}

include/jlcxx/stl.hpp

+82-74
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,57 @@ using stltypes = remove_duplicates<combine_parameterlists<combine_parameterlists
8484
jl_value_t*
8585
>, fundamental_int_types>, fixed_int_types>>;
8686

87+
88+
template<typename T>
89+
struct ReferenceTypes
90+
{
91+
using const_reference = typename T::const_reference;
92+
using reference = typename T::reference;
93+
};
94+
95+
template<template<typename...> class ContainerT, typename... TupleArgs, typename... Args>
96+
struct ReferenceTypes<ContainerT<std::tuple<TupleArgs...>, Args...>>
97+
{
98+
using const_reference = std::tuple<TupleArgs...>;
99+
using reference = const_reference;
100+
};
101+
102+
template<template<typename...> class ContainerT, typename... Args>
103+
struct ReferenceTypes<ContainerT<bool, Args...>>
104+
{
105+
using const_reference = bool;
106+
using reference = bool;
107+
};
108+
109+
template<typename T>
110+
struct ReferenceTypes<std::valarray<T>>
111+
{
112+
using const_reference = const T&;
113+
using reference = T&;
114+
};
115+
116+
template<>
117+
struct ReferenceTypes<std::valarray<bool>>
118+
{
119+
using const_reference = bool;
120+
using reference = bool;
121+
};
122+
123+
template<typename T>
124+
using const_reftype = typename ReferenceTypes<T>::const_reference;
125+
126+
template<typename T>
127+
using reftype = typename ReferenceTypes<T>::reference;
128+
129+
87130
template<typename TypeWrapperT>
88131
void wrap_range_based_fill([[maybe_unused]] TypeWrapperT& wrapped)
89132
{
90133
#ifdef JLCXX_HAS_RANGES
91134
using WrappedT = typename TypeWrapperT::type;
92135
using T = typename WrappedT::value_type;
93136
wrapped.module().set_override_module(stl_module());
94-
wrapped.method("StdFill", [] (WrappedT& v, const T& val) { std::ranges::fill(v, val); });
137+
wrapped.method("StdFill", [] (WrappedT& v, const_reftype<WrappedT> val) { std::ranges::fill(v, val); });
95138
wrapped.module().unset_override_module();
96139
#endif
97140
}
@@ -112,7 +155,7 @@ void wrap_range_based_bsearch([[maybe_unused]] TypeWrapperT& wrapped)
112155
if constexpr(has_less<T>)
113156
{
114157
wrapped.module().set_override_module(stl_module());
115-
wrapped.method("StdBinarySearch", [] (WrappedT& v, const T& val) { return std::ranges::binary_search(v, val); });
158+
wrapped.method("StdBinarySearch", [] (WrappedT& v, const_reftype<WrappedT> val) { return std::ranges::binary_search(v, val); });
116159
wrapped.module().unset_override_module();
117160
}
118161
#endif
@@ -247,27 +290,10 @@ struct WrapVectorImpl
247290

248291
wrap_range_based_bsearch(wrapped);
249292
wrapped.module().set_override_module(stl_module());
250-
wrapped.method("push_back", static_cast<void (WrappedT::*)(const T&)>(&WrappedT::push_back));
251-
wrapped.method("cxxgetindex", [] (const WrappedT& v, cxxint_t i) -> typename WrappedT::const_reference { return v[i-1]; });
252-
wrapped.method("cxxgetindex", [] (WrappedT& v, cxxint_t i) -> typename WrappedT::reference { return v[i-1]; });
253-
wrapped.method("cxxsetindex!", [] (WrappedT& v, const T& val, cxxint_t i) { v[i-1] = val; });
254-
wrapped.module().unset_override_module();
255-
}
256-
};
257-
258-
template<>
259-
struct WrapVectorImpl<bool>
260-
{
261-
template<typename TypeWrapperT>
262-
static void wrap(TypeWrapperT&& wrapped)
263-
{
264-
using WrappedT = std::vector<bool>;
265-
266-
wrap_range_based_bsearch(wrapped);
267-
wrapped.module().set_override_module(stl_module());
268-
wrapped.method("push_back", [] (WrappedT& v, const bool val) { v.push_back(val); });
269-
wrapped.method("cxxgetindex", [] (const WrappedT& v, cxxint_t i) { return bool(v[i-1]); });
270-
wrapped.method("cxxsetindex!", [] (WrappedT& v, const bool val, cxxint_t i) { v[i-1] = val; });
293+
wrapped.method("push_back", [] (WrappedT& v, const_reftype<WrappedT> val) { v.push_back(val); });
294+
wrapped.method("cxxgetindex", [] (const WrappedT& v, cxxint_t i) -> const_reftype<WrappedT> { return v[i-1]; });
295+
wrapped.method("cxxgetindex", [] (WrappedT& v, cxxint_t i) -> reftype<WrappedT> { return v[i-1]; });
296+
wrapped.method("cxxsetindex!", [] (WrappedT& v, const_reftype<WrappedT> val, cxxint_t i) { v[i-1] = val; });
271297
wrapped.module().unset_override_module();
272298
}
273299
};
@@ -318,9 +344,9 @@ struct WrapSTLContainer<std::valarray> : STLTypeWrapperBase<WrapSTLContainer<std
318344
wrapped.module().set_override_module(stl_module());
319345
wrapped.method("cppsize", &WrappedT::size);
320346
wrapped.method("resize", [] (WrappedT& v, const cxxint_t s) { v.resize(s); });
321-
wrapped.method("cxxgetindex", [] (const WrappedT& v, cxxint_t i) { return v[i-1]; });
322-
wrapped.method("cxxgetindex", [] (WrappedT& v, cxxint_t i) { return v[i-1]; });
323-
wrapped.method("cxxsetindex!", [] (WrappedT& v, const T& val, cxxint_t i) { v[i-1] = val; });
347+
wrapped.method("cxxgetindex", [] (const WrappedT& v, cxxint_t i) -> const_reftype<WrappedT> { return v[i-1]; });
348+
wrapped.method("cxxgetindex", [] (WrappedT& v, cxxint_t i) -> reftype<WrappedT> { return v[i-1]; });
349+
wrapped.method("cxxsetindex!", [] (WrappedT& v, const_reftype<WrappedT> val, cxxint_t i) { v[i-1] = val; });
324350
wrapped.module().unset_override_module();
325351
}
326352
};
@@ -342,10 +368,10 @@ struct WrapSTLContainer<std::deque> : STLTypeWrapperBase<WrapSTLContainer<std::d
342368
wrapped.module().set_override_module(stl_module());
343369
wrapped.method("cppsize", &WrappedT::size);
344370
wrapped.method("resize", [](WrappedT &v, const cxxint_t s) { v.resize(s); });
345-
wrapped.method("cxxgetindex", [](const WrappedT& v, cxxint_t i) { return v[i - 1]; });
346-
wrapped.method("cxxsetindex!", [](WrappedT& v, const T& val, cxxint_t i) { v[i - 1] = val; });
347-
wrapped.method("push_back!", [] (WrappedT& v, const T& val) { v.push_back(val); });
348-
wrapped.method("push_front!", [] (WrappedT& v, const T& val) { v.push_front(val); });
371+
wrapped.method("cxxgetindex", [](const WrappedT& v, cxxint_t i) -> const_reftype<WrappedT> { return v[i - 1]; });
372+
wrapped.method("cxxsetindex!", [](WrappedT& v, const_reftype<WrappedT> val, cxxint_t i) { v[i - 1] = val; });
373+
wrapped.method("push_back!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.push_back(val); });
374+
wrapped.method("push_front!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.push_front(val); });
349375
wrapped.method("pop_back!", [] (WrappedT& v) { v.pop_back(); });
350376
wrapped.method("pop_front!", [] (WrappedT& v) { v.pop_front(); });
351377
wrapped.method("iteratorbegin", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.begin()}; });
@@ -365,25 +391,7 @@ struct WrapQueueImpl
365391
wrapped.module().set_override_module(stl_module());
366392
wrapped.method("cppsize", &WrappedT::size);
367393
wrapped.method("q_empty", [] (WrappedT& v) { return v.empty(); });
368-
wrapped.method("push_back!", [] (WrappedT& v, const T& val) { v.push(val); });
369-
wrapped.method("front", [] (WrappedT& v) { return v.front(); });
370-
wrapped.method("pop_front!", [] (WrappedT& v) { v.pop(); });
371-
wrapped.module().unset_override_module();
372-
}
373-
};
374-
375-
template<>
376-
struct WrapQueueImpl<bool>
377-
{
378-
template<typename TypeWrapperT>
379-
static void wrap(TypeWrapperT&& wrapped)
380-
{
381-
using WrappedT = std::queue<bool>;
382-
383-
wrapped.module().set_override_module(stl_module());
384-
wrapped.method("cppsize", &WrappedT::size);
385-
wrapped.method("q_empty", [] (WrappedT& v) { return v.empty(); });
386-
wrapped.method("push_back!", [] (WrappedT& v, const bool val) { v.push(val); });
394+
wrapped.method("push_back!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.push(val); });
387395
wrapped.method("front", [] (WrappedT& v) { return v.front(); });
388396
wrapped.method("pop_front!", [] (WrappedT& v) { v.pop(); });
389397
wrapped.module().unset_override_module();
@@ -420,7 +428,7 @@ struct WrapSTLContainer<std::priority_queue> : STLTypeWrapperBase<WrapSTLContain
420428
wrapped.template constructor<>();
421429
wrapped.module().set_override_module(stl_module());
422430
wrapped.method("cppsize", &WrappedT::size);
423-
wrapped.method("pq_push!", [] (WrappedT& v, const T& val) { v.push(val); });
431+
wrapped.method("pq_push!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.push(val); });
424432
wrapped.method("pq_pop!", [] (WrappedT& v) { v.pop(); });
425433
if constexpr(std::is_same<T,bool>::value)
426434
{
@@ -451,7 +459,7 @@ struct WrapSTLContainer<std::stack> : STLTypeWrapperBase<WrapSTLContainer<std::s
451459
wrapped.module().set_override_module(stl_module());
452460
wrapped.method("cppsize", &WrappedT::size);
453461
wrapped.method("stack_isempty", [] (WrappedT& v) { return v.empty(); });
454-
wrapped.method("stack_push!", [] (WrappedT& v, const T& val) { v.push(val); });
462+
wrapped.method("stack_push!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.push(val); });
455463
wrapped.method("stack_top", [] (WrappedT& v) { return v.top(); });
456464
wrapped.method("stack_pop!", [] (WrappedT& v) { v.pop(); });
457465
wrapped.module().unset_override_module();
@@ -474,18 +482,18 @@ struct WrapSTLContainer<std::set> : STLTypeWrapperBase<WrapSTLContainer<std::set
474482
wrapped.template constructor<>();
475483
wrapped.module().set_override_module(stl_module());
476484
wrapped.method("cppsize", &WrappedT::size);
477-
wrapped.method("set_insert!", [] (WrappedT& v, const T& val) { v.insert(val); });
485+
wrapped.method("set_insert!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.insert(val); });
478486
wrapped.method("set_empty!", [] (WrappedT& v) { v.clear(); });
479487
wrapped.method("set_isempty", [] (WrappedT& v) { return v.empty(); });
480-
wrapped.method("set_delete!", [] (WrappedT&v, const T& val) { v.erase(val); });
481-
wrapped.method("set_in", [] (WrappedT& v, const T& val) { return v.count(val) != 0; });
488+
wrapped.method("set_delete!", [] (WrappedT&v, const_reftype<WrappedT> val) { v.erase(val); });
489+
wrapped.method("set_in", [] (WrappedT& v, const_reftype<WrappedT> val) { return v.count(val) != 0; });
482490
wrapped.method("iteratorbegin", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.begin()}; });
483491
wrapped.method("iteratorend", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.end()}; });
484492
#ifdef JLCXX_HAS_RANGES
485493
if constexpr(has_less<T>)
486494
{
487-
wrapped.method("StdUpperBound", [] (WrappedT& v, const T& val) { return iterator_wrapper_type<WrappedT>{std::ranges::upper_bound(v, val)}; });
488-
wrapped.method("StdLowerBound", [] (WrappedT& v, const T& val) { return iterator_wrapper_type<WrappedT>{std::ranges::lower_bound(v, val)}; });
495+
wrapped.method("StdUpperBound", [] (WrappedT& v, const_reftype<WrappedT> val) { return iterator_wrapper_type<WrappedT>{std::ranges::upper_bound(v, val)}; });
496+
wrapped.method("StdLowerBound", [] (WrappedT& v, const_reftype<WrappedT> val) { return iterator_wrapper_type<WrappedT>{std::ranges::lower_bound(v, val)}; });
489497
}
490498
#endif
491499
wrapped.module().unset_override_module();
@@ -507,11 +515,11 @@ struct WrapSTLContainer<std::unordered_set> : STLTypeWrapperBase<WrapSTLContaine
507515
wrapped.template constructor<>();
508516
wrapped.module().set_override_module(stl_module());
509517
wrapped.method("cppsize", &WrappedT::size);
510-
wrapped.method("set_insert!", [] (WrappedT& v, const T& val) { v.insert(val); });
518+
wrapped.method("set_insert!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.insert(val); });
511519
wrapped.method("set_empty!", [] (WrappedT& v) { v.clear(); });
512520
wrapped.method("set_isempty", [] (WrappedT& v) { return v.empty(); });
513-
wrapped.method("set_delete!", [] (WrappedT&v, const T& val) { v.erase(val); });
514-
wrapped.method("set_in", [] (WrappedT& v, const T& val) { return v.count(val) != 0; });
521+
wrapped.method("set_delete!", [] (WrappedT&v, const_reftype<WrappedT> val) { v.erase(val); });
522+
wrapped.method("set_in", [] (WrappedT& v, const_reftype<WrappedT> val) { return v.count(val) != 0; });
515523
wrapped.method("iteratorbegin", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.begin()}; });
516524
wrapped.method("iteratorend", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.end()}; });
517525
wrapped.module().unset_override_module();
@@ -534,19 +542,19 @@ struct WrapSTLContainer<std::multiset> : STLTypeWrapperBase<WrapSTLContainer<std
534542
wrapped.template constructor<>();
535543
wrapped.module().set_override_module(stl_module());
536544
wrapped.method("cppsize", &WrappedT::size);
537-
wrapped.method("multiset_insert!", [] (WrappedT& v, const T& val) { v.insert(val); });
545+
wrapped.method("multiset_insert!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.insert(val); });
538546
wrapped.method("multiset_empty!", [] (WrappedT& v) { v.clear(); });
539547
wrapped.method("multiset_isempty", [] (WrappedT& v) { return v.empty(); });
540-
wrapped.method("multiset_delete!", [] (WrappedT&v, const T& val) { v.erase(val); });
541-
wrapped.method("multiset_in", [] (WrappedT& v, const T& val) { return v.count(val) != 0; });
542-
wrapped.method("multiset_count", [] (WrappedT& v, const T& val) { return v.count(val); });
548+
wrapped.method("multiset_delete!", [] (WrappedT&v, const_reftype<WrappedT> val) { v.erase(val); });
549+
wrapped.method("multiset_in", [] (WrappedT& v, const_reftype<WrappedT> val) { return v.count(val) != 0; });
550+
wrapped.method("multiset_count", [] (WrappedT& v, const_reftype<WrappedT> val) { return v.count(val); });
543551
wrapped.method("iteratorbegin", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.begin()}; });
544552
wrapped.method("iteratorend", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.end()}; });
545553
#ifdef JLCXX_HAS_RANGES
546554
if constexpr(has_less<T>)
547555
{
548-
wrapped.method("StdUpperBound", [] (WrappedT& v, const T& val) { return iterator_wrapper_type<WrappedT>{std::ranges::upper_bound(v, val)}; });
549-
wrapped.method("StdLowerBound", [] (WrappedT& v, const T& val) { return iterator_wrapper_type<WrappedT>{std::ranges::lower_bound(v, val)}; });
556+
wrapped.method("StdUpperBound", [] (WrappedT& v, const_reftype<WrappedT> val) { return iterator_wrapper_type<WrappedT>{std::ranges::upper_bound(v, val)}; });
557+
wrapped.method("StdLowerBound", [] (WrappedT& v, const_reftype<WrappedT> val) { return iterator_wrapper_type<WrappedT>{std::ranges::lower_bound(v, val)}; });
550558
}
551559
#endif
552560
wrapped.module().unset_override_module();
@@ -568,12 +576,12 @@ struct WrapSTLContainer<std::unordered_multiset> : STLTypeWrapperBase<WrapSTLCon
568576
wrapped.template constructor<>();
569577
wrapped.module().set_override_module(stl_module());
570578
wrapped.method("cppsize", &WrappedT::size);
571-
wrapped.method("multiset_insert!", [] (WrappedT& v, const T& val) { v.insert(val); });
579+
wrapped.method("multiset_insert!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.insert(val); });
572580
wrapped.method("multiset_empty!", [] (WrappedT& v) { v.clear(); });
573581
wrapped.method("multiset_isempty", [] (WrappedT& v) { return v.empty(); });
574-
wrapped.method("multiset_delete!", [] (WrappedT&v, const T& val) { v.erase(val); });
575-
wrapped.method("multiset_in", [] (WrappedT& v, const T& val) { return v.count(val) != 0; });
576-
wrapped.method("multiset_count", [] (WrappedT& v, const T& val) { return v.count(val); });
582+
wrapped.method("multiset_delete!", [] (WrappedT&v, const_reftype<WrappedT> val) { v.erase(val); });
583+
wrapped.method("multiset_in", [] (WrappedT& v, const_reftype<WrappedT> val) { return v.count(val) != 0; });
584+
wrapped.method("multiset_count", [] (WrappedT& v, const_reftype<WrappedT> val) { return v.count(val); });
577585
wrapped.method("iteratorbegin", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.begin()}; });
578586
wrapped.method("iteratorend", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.end()}; });
579587
wrapped.module().unset_override_module();
@@ -601,17 +609,17 @@ struct WrapSTLContainer<std::list> : STLTypeWrapperBase<WrapSTLContainer<std::li
601609
wrapped.method("list_isempty", [] (WrappedT& v) { return v.empty(); });
602610
wrapped.method("list_front", [] (WrappedT& v) { return v.front(); });
603611
wrapped.method("list_back", [] (WrappedT& v) { return v.back(); });
604-
wrapped.method("list_push_back!", [] (WrappedT& v, const T& val) { v.push_back(val); });
605-
wrapped.method("list_push_front!", [] (WrappedT& v, const T& val) { v.push_front(val); });
612+
wrapped.method("list_push_back!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.push_back(val); });
613+
wrapped.method("list_push_front!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.push_front(val); });
606614
wrapped.method("list_pop_back!", [] (WrappedT& v) { v.pop_back(); });
607615
wrapped.method("list_pop_front!", [] (WrappedT& v) { v.pop_front(); });
608616
wrapped.method("iteratorbegin", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.begin()}; });
609617
wrapped.method("iteratorend", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.end()}; });
610618
#ifdef JLCXX_HAS_RANGES
611619
if constexpr(has_less<T>)
612620
{
613-
wrapped.method("StdUpperBound", [] (WrappedT& v, const T& val) { return iterator_wrapper_type<WrappedT>{std::ranges::upper_bound(v, val)}; });
614-
wrapped.method("StdLowerBound", [] (WrappedT& v, const T& val) { return iterator_wrapper_type<WrappedT>{std::ranges::lower_bound(v, val)}; });
621+
wrapped.method("StdUpperBound", [] (WrappedT& v, const_reftype<WrappedT> val) { return iterator_wrapper_type<WrappedT>{std::ranges::upper_bound(v, val)}; });
622+
wrapped.method("StdLowerBound", [] (WrappedT& v, const_reftype<WrappedT> val) { return iterator_wrapper_type<WrappedT>{std::ranges::lower_bound(v, val)}; });
615623
wrapped.method("StdListSort", [] (WrappedT& v) { v.sort(); });
616624
}
617625
#endif
@@ -637,7 +645,7 @@ struct WrapSTLContainer<std::forward_list> : STLTypeWrapperBase<WrapSTLContainer
637645
wrapped.method("flist_empty!", [] (WrappedT& v) { v.clear(); });
638646
wrapped.method("flist_isempty", [] (WrappedT& v) { return v.empty(); });
639647
wrapped.method("flist_front", [] (WrappedT& v) { return v.front(); });
640-
wrapped.method("flist_push_front!", [] (WrappedT& v, const T& val) { v.push_front(val); });
648+
wrapped.method("flist_push_front!", [] (WrappedT& v, const_reftype<WrappedT> val) { v.push_front(val); });
641649
wrapped.method("flist_pop_front!", [] (WrappedT& v) { v.pop_front(); });
642650
wrapped.method("iteratorbegin", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.begin()}; });
643651
wrapped.method("iteratorend", [] (WrappedT& v) { return iterator_wrapper_type<WrappedT>{v.end()}; });

0 commit comments

Comments
 (0)