Skip to content

Commit

Permalink
Add template deduction guide for Slice constructor
Browse files Browse the repository at this point in the history
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
  • Loading branch information
JonathonReinhart committed Feb 27, 2025
1 parent 94e8e46 commit 8eed1f7
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 5 deletions.
7 changes: 7 additions & 0 deletions include/cxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,13 @@ class Slice final
std::array<std::uintptr_t, 2> repr;
};

// Slice<T> template deduction guides
#ifdef __cpp_deduction_guides
template <typename C>
explicit Slice(C &c)
-> Slice<std::remove_reference_t<decltype(*std::declval<C>().data())>>;
#endif // __cpp_deduction_guides

template <typename T>
class Slice<T>::iterator final {
public:
Expand Down
79 changes: 74 additions & 5 deletions tests/ffi/tests.cc
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#include "tests/ffi/tests.h"
#include "tests/ffi/lib.rs.h"
#include <array>
#include <cstdlib>
#include <cstring>
#include <iterator>
#include <memory>
#include <numeric>
#ifdef __cpp_lib_span
#include <span>
#endif // __cpp_lib_span
#include <stdexcept>
#include <string>
#include <tuple>
Expand Down Expand Up @@ -891,11 +895,76 @@ 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<int> cpp_vec{1, 2, 3};
rust::Slice<int> 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);
// Test Slice<T> explicit constructor from container
{
std::vector<int> cpp_vec{1, 2, 3};
rust::Slice<int> 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);
}

// Test Slice<T> template deduction guides
#ifdef __cpp_deduction_guides
// std::array
{
// std::array<T> -> Slice<T>
std::array<int, 3> cpp_array{1, 2, 3};
auto auto_slice_of_cpp_array = rust::Slice(cpp_array);
static_assert(
std::is_same_v<decltype(auto_slice_of_cpp_array), rust::Slice<int>>);
}
{
// const std::array<T> -> Slice<const T>
const std::array<int, 3> cpp_array{1, 2, 3};
auto auto_slice_of_cpp_array = rust::Slice(cpp_array);
static_assert(std::is_same_v<decltype(auto_slice_of_cpp_array),
rust::Slice<const int>>);
}
{
// std::array<const T> -> Slice<const T>
std::array<const int, 3> cpp_array{1, 2, 3};
auto auto_slice_of_cpp_array = rust::Slice(cpp_array);
static_assert(std::is_same_v<decltype(auto_slice_of_cpp_array),
rust::Slice<const int>>);
}

// std::vector
{
// std::vector<T> -> Slice<T>
std::vector<int> cpp_vec{1, 2, 3};
auto auto_slice_of_cpp_vec = rust::Slice(cpp_vec);
static_assert(
std::is_same_v<decltype(auto_slice_of_cpp_vec), rust::Slice<int>>);
}
{
// const std::vector<T> -> Slice<const T>
const std::vector<int> cpp_vec{1, 2, 3};
auto auto_slice_of_cpp_vec = rust::Slice(cpp_vec);
static_assert(std::is_same_v<decltype(auto_slice_of_cpp_vec),
rust::Slice<const int>>);
}

#ifdef __cpp_lib_span
// std::span
{
// std::array<T> -> Slice<T>
std::array<int, 3> cpp_array{1, 2, 3};
std::span<int> cpp_span(cpp_array);
auto auto_slice_of_cpp_array = rust::Slice(cpp_span);
static_assert(
std::is_same_v<decltype(auto_slice_of_cpp_array), rust::Slice<int>>);
}
{
// const std::array<T> -> Slice<const T>
const std::array<int, 3> cpp_array{1, 2, 3};
std::span<const int> cpp_span(cpp_array);
auto auto_slice_of_cpp_array = rust::Slice(cpp_span);
static_assert(std::is_same_v<decltype(auto_slice_of_cpp_array),
rust::Slice<const int>>);
}
#endif // __cpp_lib_span
#endif // __cpp_deduction_guides

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

0 comments on commit 8eed1f7

Please sign in to comment.