From feacee076eead437c0b813102d15f9ebf730a2c5 Mon Sep 17 00:00:00 2001 From: Lukasz Anforowicz Date: Tue, 13 Aug 2024 19:50:23 +0000 Subject: [PATCH] Ergonomics: allow constructing `rust::Slice` from any C++ container. After this commit, it is possible to explicitly construct `rust::Slice` from a reference to any continguous C++ container (any container that exposes `data` and `size` accessors). The new constructor results in a slightly more ergonomic code, by removing the need to explicit extract and pass `c.data()` and `c.size()` at a callsite of a `rust::Slice` constructor. The callsites using the new constructor are also more obviously correct, because they doesn't require double-checking that the passed `data` and `size` match. The implementation of the new constructor mimics `std::span` from C++20, but for C++11 compatibility reimplements `std::size` / `std::ranges::size` in a pedestrian way (same for `std::data` / `std::ranges::data`). --- include/cxx.h | 3 +++ tests/ffi/tests.cc | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/include/cxx.h b/include/cxx.h index 002282551..3414e4c8a 100644 --- a/include/cxx.h +++ b/include/cxx.h @@ -176,6 +176,9 @@ class Slice final Slice() noexcept; Slice(T *, std::size_t count) noexcept; + template + explicit Slice(C& c) : Slice(c.data(), c.size()) {} + Slice &operator=(const Slice &) &noexcept = default; Slice &operator=(Slice &&) &noexcept = default; diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index 8cf74bebb..ca71276f8 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -884,6 +884,12 @@ extern "C" const char *cxx_run_test() noexcept { rust::String bad_utf16_rstring = rust::String::lossy(bad_utf16_literal); ASSERT(bad_utf8_rstring == bad_utf16_rstring); + std::vector cpp_vec{1, 2, 3}; + rust::Slice slice_of_cpp_vec(cpp_vec); + ASSERT(slice_of_cpp_vec.data() == cpp_vec.data()); + ASSERT(slice_of_cpp_vec.size() == cpp_vec.size()); + ASSERT(slice_of_cpp_vec[0] == 1); + rust::Vec vec1{1, 2}; rust::Vec vec2{3, 4}; swap(vec1, vec2);