Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rtree extern template instantiation with interprocess compile error #1276

Open
addy90 opened this issue Apr 26, 2024 · 0 comments
Open

rtree extern template instantiation with interprocess compile error #1276

addy90 opened this issue Apr 26, 2024 · 0 comments

Comments

@addy90
Copy link

addy90 commented Apr 26, 2024

Dear friends,

I am trying to extern template instantiate the boost::geometry::rtree with boost::interprocess allocator, since I need it in multiple translation units and the (very appreciated) rtree implementation generates a lot of code bloat.

When using a stateless allocator, such as std::allocator, this works. However when using a stateful allocator such as boost::interprocess, it does not compile due to three default constructors around the rtree code that call the default constructor of the allocator, which does not exist for stateful allocators for obvious reasons.

Here is a basic example that does not compile when the extern template declaration and respective initialization are uncommented (sometimes the code compilation gives timeout, then retry, or compile it locally):
https://godbolt.org/z/EbGohf167
Also attached:
project-2024 04 2610 46 28.zip

The error message is here:

Open to review
Step cmake returned: 0
-- The C compiler identification is GNU 13.2.0
-- The CXX compiler identification is GNU 13.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /opt/compiler-explorer/gcc-13.2.0/bin/gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /opt/compiler-explorer/gcc-13.2.0/bin/g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.3s)
-- Generating done (0.0s)
-- Build files have been written to: /app/build
Step build returned: 2
[ 33%] Building CXX object CMakeFiles/index.dir/main.cpp.o
[ 66%] Building CXX object CMakeFiles/index.dir/index.cpp.o
In file included from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/index/detail/rtree/node/node.hpp:37,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/index/rtree.hpp:64,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/algorithms/detail/within/multi_point.hpp:38,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/algorithms/detail/within/implementation.hpp:30,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/algorithms/detail/covered_by/implementation.hpp:26,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/algorithms/covered_by.hpp:24,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp:32,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp:30,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/algorithms/detail/buffer/implementation.hpp:24,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/algorithms/buffer.hpp:22,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/geometry.hpp:63,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/geometry.hpp:17,
                 from /app/index.hpp:3,
                 from /app/index.cpp:1:
/opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/index/detail/rtree/node/variant_static.hpp: In instantiation of 'boost::geometry::index::detail::rtree::allocators<Allocator, Value, Parameters, Box, boost::geometry::index::detail::rtree::node_variant_static_tag>::allocators() [with Allocator = boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >; Value = std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>; Parameters = boost::geometry::index::rstar<16>; Box = boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >]':
/opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/index/rtree.hpp:290:21:   required from 'boost::geometry::index::rtree<Value, Options, IndexableGetter, EqualTo, Allocator>::members_holder::members_holder(const IndGet&, const ValEq&, const Parameters&) [with IndGet = boost::geometry::index::indexable<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int> >; ValEq = boost::geometry::index::equal_to<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int> >; Value = std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>; Parameters = boost::geometry::index::rstar<16>; IndexableGetter = boost::geometry::index::indexable<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int> >; EqualTo = boost::geometry::index::equal_to<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int> >; Allocator = boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >]'
/opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/index/rtree.hpp:367:11:   required from 'boost::geometry::index::rtree<Value, Options, IndexableGetter, EqualTo, Allocator>::rtree(const parameters_type&, const indexable_getter&, const value_equal&) [with Value = std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>; Parameters = boost::geometry::index::rstar<16>; IndexableGetter = boost::geometry::index::indexable<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int> >; EqualTo = boost::geometry::index::equal_to<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int> >; Allocator = boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >; parameters_type = boost::geometry::index::rstar<16>; indexable_getter = boost::geometry::index::indexable<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int> >; value_equal = boost::geometry::index::equal_to<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int> >]'
/app/index.cpp:13:31:   required from here
/opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/index/detail/rtree/node/variant_static.hpp:129:31: error: no matching function for call to 'boost::interprocess::allocator<boost::variant<boost::geometry::index::detail::rtree::variant_leaf<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::allocators<boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >, std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::variant_internal_node<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16, 4, 4, 32>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::allocators<boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0>, 0>, boost::interprocess::iset_index> >, std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16, 4, 4, 32>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::node_variant_static_tag> >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >::allocator()'
  129 |         : node_allocator_type()
      |                               ^
In file included from /opt/compiler-explorer/libs/boost_1_84_0/boost/interprocess/segment_manager.hpp:38,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/interprocess/detail/managed_memory_impl.hpp:30,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/interprocess/managed_shared_memory.hpp:25,
                 from /app/index.hpp:7:
/opt/compiler-explorer/libs/boost_1_84_0/boost/interprocess/allocators/allocator.hpp:142:4: note: candidate: 'template<class T2> boost::interprocess::allocator<T, SegmentManager>::allocator(const boost::interprocess::allocator<T2, SegmentManager>&) [with T = boost::variant<boost::geometry::index::detail::rtree::variant_leaf<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::allocators<boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >, std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::variant_internal_node<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16, 4, 4, 32>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::allocators<boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0>, 0>, boost::interprocess::iset_index> >, std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16, 4, 4, 32>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::node_variant_static_tag> >; SegmentManager = boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index>]'
  142 |    allocator(const allocator<T2, SegmentManager> &other)
      |    ^~~~~~~~~
/opt/compiler-explorer/libs/boost_1_84_0/boost/interprocess/allocators/allocator.hpp:142:4: note:   template argument deduction/substitution failed:
/opt/compiler-explorer/libs/boost_1_84_0/boost/geometry/index/detail/rtree/node/variant_static.hpp:129:31: note:   candidate expects 1 argument, 0 provided
  129 |         : node_allocator_type()
      |                               ^
/opt/compiler-explorer/libs/boost_1_84_0/boost/interprocess/allocators/allocator.hpp:136:4: note: candidate: 'boost::interprocess::allocator<T, SegmentManager>::allocator(const boost::interprocess::allocator<T, SegmentManager>&) [with T = boost::variant<boost::geometry::index::detail::rtree::variant_leaf<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::allocators<boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >, std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::variant_internal_node<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16, 4, 4, 32>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::allocators<boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0>, 0>, boost::interprocess::iset_index> >, std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16, 4, 4, 32>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::node_variant_static_tag> >; SegmentManager = boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index>]'
  136 |    allocator(const allocator &other)
      |    ^~~~~~~~~
/opt/compiler-explorer/libs/boost_1_84_0/boost/interprocess/allocators/allocator.hpp:136:4: note:   candidate expects 1 argument, 0 provided
/opt/compiler-explorer/libs/boost_1_84_0/boost/interprocess/allocators/allocator.hpp:131:4: note: candidate: 'boost::interprocess::allocator<T, SegmentManager>::allocator(segment_manager*) [with T = boost::variant<boost::geometry::index::detail::rtree::variant_leaf<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::allocators<boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >, std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::variant_internal_node<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16, 4, 4, 32>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::allocators<boost::interprocess::allocator<std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0>, 0>, boost::interprocess::iset_index> >, std::pair<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>, long unsigned int>, boost::geometry::index::rstar<16, 4, 4, 32>, boost::geometry::model::box<boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> >, boost::geometry::index::detail::rtree::node_variant_static_tag>, boost::geometry::index::detail::rtree::node_variant_static_tag> >; SegmentManager = boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index>; segment_manager = boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index>]'
  131 |    allocator(segment_manager *segment_mngr)
      |    ^~~~~~~~~
/opt/compiler-explorer/libs/boost_1_84_0/boost/interprocess/allocators/allocator.hpp:131:4: note:   candidate expects 1 argument, 0 provided
gmake[2]: *** [CMakeFiles/index.dir/build.make:90: CMakeFiles/index.dir/index.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/index.dir/all] Error 2
gmake: *** [Makefile:91: all] Error 2

When no explicit template instantiation is used, the code compiles for obvious reasons, since the client code in the main.cpp does not use the default constructor of the rtree but the explicit one with allocators, however the explicit instantiation wants to compile the default constructors.

There need to be made three changes by applying std::enable_if to three constructors. The error message only shows the first error, after fixing it, two more arise. I attached the changes as patch file here:
index.patch

The idea is to enable the constructors that call the default allocator constructor only when the given allocator template is default initializable. So the idea is to disable every rtree and node constructor that calls a non-existing constructor of the allocator.

Then the code compiles without error, since the default constructor of the allocator is not called anymore. Please feel free to adapt the style to your liking!

I know that this solution has its caveats, however I don't know any other solution to this problem besides C++20 requires clauses.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant