Skip to content

Commit 8eed1f7

Browse files
Add template deduction guide for Slice constructor
PR #1367 added an explicit Slice constructor which allows constructing from any C++ container. This adds a template deduction guide for that constructor which allows the Slice type to be inferred from the container's contained type. This applies to C++17 only. Note that, because C can be any type of container, we need to use a template template parameter. Test: cargo test Test: cargo test -F c++14 Test: cargo test -F c++17 Test: cargo test -F c++20
1 parent 94e8e46 commit 8eed1f7

File tree

2 files changed

+81
-5
lines changed

2 files changed

+81
-5
lines changed

include/cxx.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,13 @@ class Slice final
220220
std::array<std::uintptr_t, 2> repr;
221221
};
222222

223+
// Slice<T> template deduction guides
224+
#ifdef __cpp_deduction_guides
225+
template <typename C>
226+
explicit Slice(C &c)
227+
-> Slice<std::remove_reference_t<decltype(*std::declval<C>().data())>>;
228+
#endif // __cpp_deduction_guides
229+
223230
template <typename T>
224231
class Slice<T>::iterator final {
225232
public:

tests/ffi/tests.cc

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
#include "tests/ffi/tests.h"
22
#include "tests/ffi/lib.rs.h"
3+
#include <array>
34
#include <cstdlib>
45
#include <cstring>
56
#include <iterator>
67
#include <memory>
78
#include <numeric>
9+
#ifdef __cpp_lib_span
10+
#include <span>
11+
#endif // __cpp_lib_span
812
#include <stdexcept>
913
#include <string>
1014
#include <tuple>
@@ -891,11 +895,76 @@ extern "C" const char *cxx_run_test() noexcept {
891895
rust::String bad_utf16_rstring = rust::String::lossy(bad_utf16_literal);
892896
ASSERT(bad_utf8_rstring == bad_utf16_rstring);
893897

894-
std::vector<int> cpp_vec{1, 2, 3};
895-
rust::Slice<int> slice_of_cpp_vec(cpp_vec);
896-
ASSERT(slice_of_cpp_vec.data() == cpp_vec.data());
897-
ASSERT(slice_of_cpp_vec.size() == cpp_vec.size());
898-
ASSERT(slice_of_cpp_vec[0] == 1);
898+
// Test Slice<T> explicit constructor from container
899+
{
900+
std::vector<int> cpp_vec{1, 2, 3};
901+
rust::Slice<int> slice_of_cpp_vec(cpp_vec);
902+
ASSERT(slice_of_cpp_vec.data() == cpp_vec.data());
903+
ASSERT(slice_of_cpp_vec.size() == cpp_vec.size());
904+
ASSERT(slice_of_cpp_vec[0] == 1);
905+
}
906+
907+
// Test Slice<T> template deduction guides
908+
#ifdef __cpp_deduction_guides
909+
// std::array
910+
{
911+
// std::array<T> -> Slice<T>
912+
std::array<int, 3> cpp_array{1, 2, 3};
913+
auto auto_slice_of_cpp_array = rust::Slice(cpp_array);
914+
static_assert(
915+
std::is_same_v<decltype(auto_slice_of_cpp_array), rust::Slice<int>>);
916+
}
917+
{
918+
// const std::array<T> -> Slice<const T>
919+
const std::array<int, 3> cpp_array{1, 2, 3};
920+
auto auto_slice_of_cpp_array = rust::Slice(cpp_array);
921+
static_assert(std::is_same_v<decltype(auto_slice_of_cpp_array),
922+
rust::Slice<const int>>);
923+
}
924+
{
925+
// std::array<const T> -> Slice<const T>
926+
std::array<const int, 3> cpp_array{1, 2, 3};
927+
auto auto_slice_of_cpp_array = rust::Slice(cpp_array);
928+
static_assert(std::is_same_v<decltype(auto_slice_of_cpp_array),
929+
rust::Slice<const int>>);
930+
}
931+
932+
// std::vector
933+
{
934+
// std::vector<T> -> Slice<T>
935+
std::vector<int> cpp_vec{1, 2, 3};
936+
auto auto_slice_of_cpp_vec = rust::Slice(cpp_vec);
937+
static_assert(
938+
std::is_same_v<decltype(auto_slice_of_cpp_vec), rust::Slice<int>>);
939+
}
940+
{
941+
// const std::vector<T> -> Slice<const T>
942+
const std::vector<int> cpp_vec{1, 2, 3};
943+
auto auto_slice_of_cpp_vec = rust::Slice(cpp_vec);
944+
static_assert(std::is_same_v<decltype(auto_slice_of_cpp_vec),
945+
rust::Slice<const int>>);
946+
}
947+
948+
#ifdef __cpp_lib_span
949+
// std::span
950+
{
951+
// std::array<T> -> Slice<T>
952+
std::array<int, 3> cpp_array{1, 2, 3};
953+
std::span<int> cpp_span(cpp_array);
954+
auto auto_slice_of_cpp_array = rust::Slice(cpp_span);
955+
static_assert(
956+
std::is_same_v<decltype(auto_slice_of_cpp_array), rust::Slice<int>>);
957+
}
958+
{
959+
// const std::array<T> -> Slice<const T>
960+
const std::array<int, 3> cpp_array{1, 2, 3};
961+
std::span<const int> cpp_span(cpp_array);
962+
auto auto_slice_of_cpp_array = rust::Slice(cpp_span);
963+
static_assert(std::is_same_v<decltype(auto_slice_of_cpp_array),
964+
rust::Slice<const int>>);
965+
}
966+
#endif // __cpp_lib_span
967+
#endif // __cpp_deduction_guides
899968

900969
rust::Vec<int> vec1{1, 2};
901970
rust::Vec<int> vec2{3, 4};

0 commit comments

Comments
 (0)