Browse Source

fix error occured by creating primitives;

minor change to primitive process framework
feat-obj-export
Zhicheng Wang 2 months ago
parent
commit
70a08acb19
  1. 30
      application/main.cpp
  2. 4
      frontend/src/implicit_surface_network_solver.cpp
  3. 8
      primitive_process/interface/base/primitive.hpp
  4. 17
      primitive_process/interface/data/data_type.hpp
  5. 18
      primitive_process/interface/primitive/simple/cylinder.hpp
  6. 14
      primitive_process/interface/primitive/simple/sphere.hpp
  7. 48
      primitive_process/src/base/primitive.cpp
  8. 12
      primitive_process/src/data/data_center.cpp
  9. 62
      primitive_process/src/primitive/simple/cylinder.cpp
  10. 31
      primitive_process/src/primitive/simple/sphere.cpp
  11. 389
      shared_module/container/span.hpp

30
application/main.cpp

@ -17,25 +17,25 @@ int main()
auto node_iter1 = blobtree_add_primitive_node(runtime_blobtree, cylinder); auto node_iter1 = blobtree_add_primitive_node(runtime_blobtree, cylinder);
auto node_iter2 = blobtree_add_primitive_node(runtime_blobtree, sphere1); auto node_iter2 = blobtree_add_primitive_node(runtime_blobtree, sphere1);
auto node_iter3 = blobtree_add_operation_node(runtime_blobtree, node_iter1, node_iter2, INTERSECTION_OP); auto node_iter3 = blobtree_add_operation_node(runtime_blobtree, node_iter1, node_iter2, INTERSECTION_OP);
auto baked_blobtree = bake_blobtree(runtime_blobtree); // auto baked_blobtree = bake_blobtree(runtime_blobtree);
destroy_blobtree(runtime_blobtree); // destroy_blobtree(runtime_blobtree);
std::cout << "blobtree created..." << std::endl; // std::cout << "blobtree created..." << std::endl;
s_settings settings{}; // s_settings settings{};
settings.resolution = 21; // settings.resolution = 21;
settings.scene_aabb_margin = 1e-5; // settings.scene_aabb_margin = 1e-5;
settings.restricted_primitive_bounding_test = true; // settings.restricted_primitive_bounding_test = true;
auto solver = create_solver(baked_blobtree, settings); // auto solver = create_solver(baked_blobtree, settings);
auto result = generate_polymesh(solver); // auto result = generate_polymesh(solver);
print_statistics(solver); // print_statistics(solver);
destroy_solver(solver); // destroy_solver(solver);
destroy_baked_blobtree(baked_blobtree); // destroy_baked_blobtree(baked_blobtree);
destroy_primitive(sphere1); // destroy_primitive(sphere1);
destroy_primitive(cylinder); // destroy_primitive(cylinder);
destroy_primitive_data_center(primitive_data_center); // destroy_primitive_data_center(primitive_data_center);
return 0; return 0;
} }

4
frontend/src/implicit_surface_network_solver.cpp

@ -8,11 +8,13 @@ void implicit_network_solver::generate_polymesh(stl_vector_mp<Eigen::Vector3d>&
{ {
// generate polymesh // generate polymesh
m_timers.push_timer("generate_polymesh"); m_timers.push_timer("generate_polymesh");
flat_hash_map_mp<uint32_t, parameteric_plane_t> temp{};
build_implicit_network_by_blobtree(m_settings, build_implicit_network_by_blobtree(m_settings,
*m_blobtree, *m_blobtree,
output_vertices, output_vertices,
output_polygon_faces, output_polygon_faces,
output_vertex_counts_of_face); output_vertex_counts_of_face,
temp);
m_timers.pop_timer("generate_polymesh"); m_timers.pop_timer("generate_polymesh");
} }

8
primitive_process/interface/base/primitive.hpp

@ -6,6 +6,7 @@
#include <utils/marked_ptr.hpp> #include <utils/marked_ptr.hpp>
#include <container/stl_alias.hpp> #include <container/stl_alias.hpp>
#include <container/dynamic_bitset.hpp> #include <container/dynamic_bitset.hpp>
#include <container/span.hpp>
#include <primitive_descriptor.h> #include <primitive_descriptor.h>
#include <data/data_type.hpp> #include <data/data_type.hpp>
@ -48,12 +49,13 @@ static inline sign_t operator&(sign_t a, sign_t b)
struct subface; struct subface;
EXTERN_C struct PE_API primitive { EXTERN_C struct PE_API primitive {
virtual void initialize(primitive_data_center_t &) = 0; void initialize(primitive_data_center_t &);
virtual void destroy() = 0; void destroy();
virtual primitive_type get_type() const = 0; virtual primitive_type get_type() const = 0;
virtual stl_vector_mp<marked_subface_ptr_t<subface>> get_subfaces() const = 0; virtual span<marked_subface_ptr_t<subface>> get_subfaces() const = 0;
virtual stl_vector_mp<surface_type> get_subface_types() const = 0; virtual stl_vector_mp<surface_type> get_subface_types() const = 0;
virtual stl_vector_mp<internal::paired_model_matrix_ptr_t> get_subface_init_model_matrices() const = 0;
// sign_t judge_sign_by_subface_sdf(const std::vector<double> &) const; // sign_t judge_sign_by_subface_sdf(const std::vector<double> &) const;
// sign_t judge_sign_by_subface_sdf_sign(const std::vector<sign_t> &) const; // sign_t judge_sign_by_subface_sdf_sign(const std::vector<sign_t> &) const;

17
primitive_process/interface/data/data_type.hpp

@ -18,8 +18,11 @@ struct paired_model_matrix {
using paired_model_matrix_ptr_t = pointer_wrapper<paired_model_matrix>; using paired_model_matrix_ptr_t = pointer_wrapper<paired_model_matrix>;
const paired_model_matrix identity_model_matrix{internal::transform_block::Identity(), internal::transform_block::Identity()}; namespace hidden
const auto plane_to_z_pos_1_model_matrix = []() { {
static inline paired_model_matrix identity_model_matrix{internal::transform_block::Identity(),
internal::transform_block::Identity()};
static inline auto plane_to_z_pos_1_model_matrix = []() {
paired_model_matrix res{}; paired_model_matrix res{};
Eigen::Matrix3d::Identity(); Eigen::Matrix3d::Identity();
res.world_to_local.linear().col(0) = Eigen::Vector3d{0, 0, 1}; res.world_to_local.linear().col(0) = Eigen::Vector3d{0, 0, 1};
@ -30,7 +33,7 @@ const auto plane_to_z_pos_1_model_matrix = []() {
res.local_to_world.translation() = Eigen::Vector3d{0, 0, 1}; res.local_to_world.translation() = Eigen::Vector3d{0, 0, 1};
return res; return res;
}(); }();
const auto plane_to_z_model_matrix = []() { static inline auto plane_to_z_model_matrix = []() {
paired_model_matrix res{}; paired_model_matrix res{};
Eigen::Matrix3d::Identity(); Eigen::Matrix3d::Identity();
res.world_to_local.linear().col(0) = Eigen::Vector3d{0, 0, 1}; res.world_to_local.linear().col(0) = Eigen::Vector3d{0, 0, 1};
@ -40,7 +43,7 @@ const auto plane_to_z_model_matrix = []() {
res.local_to_world = res.world_to_local; res.local_to_world = res.world_to_local;
return res; return res;
}(); }();
const auto plane_to_z_neg_1_model_matrix = []() { static inline auto plane_to_z_neg_1_model_matrix = []() {
paired_model_matrix res{}; paired_model_matrix res{};
res.world_to_local.linear().col(0) = Eigen::Vector3d{0, 0, 1}; res.world_to_local.linear().col(0) = Eigen::Vector3d{0, 0, 1};
res.world_to_local.linear().col(1) = Eigen::Vector3d{0, 1, 0}; res.world_to_local.linear().col(1) = Eigen::Vector3d{0, 1, 0};
@ -50,6 +53,12 @@ const auto plane_to_z_neg_1_model_matrix = []() {
res.local_to_world.translation() = Eigen::Vector3d{0, 0, -1}; res.local_to_world.translation() = Eigen::Vector3d{0, 0, -1};
return res; return res;
}(); }();
} // namespace hidden
const auto identity_model_matrix_ptr = make_pointer_wrapper(hidden::identity_model_matrix);
const auto plane_to_z_pos_1_model_matrix_ptr = make_pointer_wrapper(hidden::plane_to_z_pos_1_model_matrix);
const auto plane_to_z_model_matrix_ptr = make_pointer_wrapper(hidden::plane_to_z_model_matrix);
const auto plane_to_z_neg_1_model_matrix_ptr = make_pointer_wrapper(hidden::plane_to_z_neg_1_model_matrix);
template <typename T> template <typename T>
using primitive_data_iterator = typename hive_mp<T>::iterator; using primitive_data_iterator = typename hive_mp<T>::iterator;

18
primitive_process/interface/primitive/simple/cylinder.hpp

@ -7,16 +7,11 @@
namespace internal namespace internal
{ {
struct cylinder_t final : public primitive { struct cylinder_t final : public primitive {
void initialize(primitive_data_center_t &) override;
void destroy() override;
primitive_type get_type() const override { return PRIMITIVE_TYPE_CYLINDER; }; primitive_type get_type() const override { return PRIMITIVE_TYPE_CYLINDER; };
stl_vector_mp<marked_subface_ptr_t<subface>> get_subfaces() const override span<marked_subface_ptr_t<subface>> get_subfaces() const override
{ {
return {static_pointer_cast<subface>(cylinder_face), return {const_cast<marked_subface_ptr_t<subface> *>(subfaces.data()), subfaces.size()};
static_pointer_cast<subface>(bottom_plane),
static_pointer_cast<subface>(top_plane)};
} }
stl_vector_mp<surface_type> get_subface_types() const override stl_vector_mp<surface_type> get_subface_types() const override
@ -24,8 +19,11 @@ struct cylinder_t final : public primitive {
return {surface_type::cylinder, surface_type::plane, surface_type::plane}; return {surface_type::cylinder, surface_type::plane, surface_type::plane};
} }
marked_subface_ptr_t<internal::cylinder_face_t> cylinder_face{}; stl_vector_mp<internal::paired_model_matrix_ptr_t> get_subface_init_model_matrices() const override
marked_subface_ptr_t<internal::plane_t> bottom_plane{}; {
marked_subface_ptr_t<internal::plane_t> top_plane{}; return {plane_to_z_model_matrix_ptr, identity_model_matrix_ptr, plane_to_z_pos_1_model_matrix_ptr};
}
std::array<marked_subface_ptr_t<subface>, 3> subfaces{};
}; };
} // namespace internal } // namespace internal

14
primitive_process/interface/primitive/simple/sphere.hpp

@ -6,18 +6,20 @@
namespace internal namespace internal
{ {
struct sphere_t final : primitive { struct sphere_t final : primitive {
void initialize(primitive_data_center_t &) override;
void destroy() override;
primitive_type get_type() const override { return PRIMITIVE_TYPE_SPHERE; }; primitive_type get_type() const override { return PRIMITIVE_TYPE_SPHERE; };
stl_vector_mp<marked_subface_ptr_t<subface>> get_subfaces() const override span<marked_subface_ptr_t<subface>> get_subfaces() const override
{ {
return {static_pointer_cast<subface>(sphere_face)}; return {const_cast<marked_subface_ptr_t<subface> *>(&sphere_face), 1};
} }
stl_vector_mp<surface_type> get_subface_types() const override { return {surface_type::sphere}; } stl_vector_mp<surface_type> get_subface_types() const override { return {surface_type::sphere}; }
marked_subface_ptr_t<internal::sphere_face_t> sphere_face{}; stl_vector_mp<internal::paired_model_matrix_ptr_t> get_subface_init_model_matrices() const override
{
return {identity_model_matrix_ptr};
}
marked_subface_ptr_t<subface> sphere_face{};
}; };
} // namespace internal } // namespace internal

48
primitive_process/src/base/primitive.cpp

@ -2,30 +2,6 @@
#include <base/subface.hpp> #include <base/subface.hpp>
#include <base/primitive.hpp> #include <base/primitive.hpp>
#include "data/data_type.hpp"
// sign_t primitive::judge_sign_by_subface_sdf(const std::vector<double> &sdf_values) const
// {
// auto subfaces = get_subface();
// sign_t res{sign_by_subface(sdf_values[0] > 0) * sign_by_subface(subfaces[0].is_marked())};
// for (size_t i = 1; i < get_subface_count(); ++i) {
// res = res & (sign_by_subface(sdf_values[i] > 0) * sign_by_subface(subfaces[i].is_marked()));
// }
// return res;
// }
// sign_t primitive::judge_sign_by_subface_sdf_sign(const std::vector<sign_t> &sdf_signs) const
// {
// auto subfaces = get_subface();
// sign_t res{sdf_signs[0] * sign_by_subface(subfaces[0].is_marked())};
// for (size_t i = 1; i < get_subface_count(); ++i) { res = res & (sdf_signs[i] * sign_by_subface(subfaces[i].is_marked()));
// }
// return res;
// }
dynamic_bitset_mp<> primitive::judge_sign_by_subface_sign(stl_vector_mp<dynamic_bitset_mp<>> subface_signs) const dynamic_bitset_mp<> primitive::judge_sign_by_subface_sign(stl_vector_mp<dynamic_bitset_mp<>> subface_signs) const
{ {
@ -42,6 +18,30 @@ dynamic_bitset_mp<> primitive::judge_sign_by_subface_sign(stl_vector_mp<dynamic_
return res; return res;
} }
void primitive::initialize(primitive_data_center_t &data_center)
{
auto subface_init_model_matrices = get_subface_init_model_matrices();
std::transform(subface_init_model_matrices.begin(),
subface_init_model_matrices.end(),
subface_init_model_matrices.begin(),
[&](internal::paired_model_matrix_ptr_t model_matrix_ptr) {
return data_center.require_transform_block(model_matrix_ptr);
});
initialize(data_center, subface_init_model_matrices);
}
void primitive::destroy()
{
auto subfaces = get_subfaces();
auto subface_types = get_subface_types();
assert(subfaces.front());
auto data_center = subfaces.front()->data_center;
assert(data_center);
for (size_t i = 0; i < subfaces.size(); ++i) data_center->release_surface(subface_types[i], subfaces[i]);
}
void primitive::apply_transform(internal::transform_type type, Eigen::Vector4d param) void primitive::apply_transform(internal::transform_type type, Eigen::Vector4d param)
{ {
auto subfaces = get_subfaces(); auto subfaces = get_subfaces();

12
primitive_process/src/data/data_center.cpp

@ -3,9 +3,9 @@
// before dtor, always keep identity transformation block // before dtor, always keep identity transformation block
primitive_data_center_t::primitive_data_center_t() noexcept primitive_data_center_t::primitive_data_center_t() noexcept
{ {
this->transform_blocks.acquire(internal::identity_model_matrix); this->transform_blocks.acquire(internal::identity_model_matrix_ptr);
this->transform_blocks.acquire(internal::plane_to_z_pos_1_model_matrix); this->transform_blocks.acquire(internal::plane_to_z_pos_1_model_matrix_ptr);
this->transform_blocks.acquire(internal::plane_to_z_neg_1_model_matrix); this->transform_blocks.acquire(internal::plane_to_z_neg_1_model_matrix_ptr);
// set hashed refcount hive container to individual surface containers // set hashed refcount hive container to individual surface containers
this->surfaces[static_cast<uint8_t>(surface_type::plane)].emplace<plane_container_t>(); this->surfaces[static_cast<uint8_t>(surface_type::plane)].emplace<plane_container_t>();
@ -15,9 +15,9 @@ primitive_data_center_t::primitive_data_center_t() noexcept
primitive_data_center_t::~primitive_data_center_t() noexcept primitive_data_center_t::~primitive_data_center_t() noexcept
{ {
this->transform_blocks.release(internal::identity_model_matrix); this->transform_blocks.release(internal::identity_model_matrix_ptr);
this->transform_blocks.release(internal::plane_to_z_pos_1_model_matrix); this->transform_blocks.release(internal::plane_to_z_pos_1_model_matrix_ptr);
this->transform_blocks.release(internal::plane_to_z_neg_1_model_matrix); this->transform_blocks.release(internal::plane_to_z_neg_1_model_matrix_ptr);
} }
auto primitive_data_center_t::require_transform_block(const internal::paired_model_matrix& matrix) auto primitive_data_center_t::require_transform_block(const internal::paired_model_matrix& matrix)

62
primitive_process/src/primitive/simple/cylinder.cpp

@ -1,62 +0,0 @@
#include <data/data_center.hpp>
namespace internal
{
void cylinder_t::initialize(primitive_data_center_t &data_center)
{
auto bottom_plane_mat = data_center.require_transform_block(internal::plane_to_z_model_matrix);
auto cylinder_mat = data_center.require_transform_block(internal::identity_model_matrix);
auto top_plane_mat = data_center.require_transform_block(internal::plane_to_z_pos_1_model_matrix);
primitive::initialize(data_center, {cylinder_mat, bottom_plane_mat, top_plane_mat});
}
void cylinder_t::destroy()
{
primitive_data_center_t &data_center = bottom_plane->data_center;
data_center.release_surface(surface_type::cylinder, static_pointer_cast<subface>(cylinder_face));
data_center.release_surface(surface_type::plane, static_pointer_cast<subface>(bottom_plane));
data_center.release_surface(surface_type::plane, static_pointer_cast<subface>(top_plane));
}
// void cylinder_t::initialize(primitive_data_center_t &data_center,
// const std::vector<std::pair<internal::paired_model_matrix *, bool>> &new_model_matrices)
// {
// std::array<subface *, 3> old_ptrs{cylinder_face.get_ptr(), bottom_plane.get_ptr(), top_plane.get_ptr()};
// std::array<paired_model_matrix *, 3> old_model_matrices{nullptr, nullptr, nullptr};
// for (size_t i = 0; i < 3; ++i) {
// if (old_ptrs[i] != nullptr) old_model_matrices[i] = old_ptrs[i]->model_matrices;
// }
// {
// auto [iter, is_new] = data_center.cylinders.acquire(cylinder_paired_model_matrix{new_model_matrices[0].first});
// cylinder_face.set_ptr(iter.operator->());
// cylinder_face.set_mark(new_model_matrices[0].second);
// if (is_new) cylinder_face.get_ptr()->data_center = &data_center;
// }
// {
// auto [iter, is_new] = data_center.planes.acquire(plane_paired_model_matrix{new_model_matrices[1].first});
// bottom_plane.set_ptr(iter.operator->());
// bottom_plane.set_mark(new_model_matrices[1].second);
// if (is_new) bottom_plane.get_ptr()->data_center = &data_center;
// }
// {
// auto [iter, is_new] = data_center.planes.acquire(plane_paired_model_matrix{new_model_matrices[2].first});
// top_plane.set_ptr(iter.operator->());
// top_plane.set_mark(new_model_matrices[2].second);
// if (is_new) top_plane.get_ptr()->data_center = &data_center;
// }
// // deferred release to avoid acquiring the same just-released subface
// {
// if (old_ptrs[0] != nullptr)
// data_center.cylinders.release(cylinder_paired_model_matrix{old_model_matrices[0]});
// if (old_ptrs[1] != nullptr)
// data_center.planes.release(plane_paired_model_matrix{old_model_matrices[1]});
// if (old_ptrs[2] != nullptr)
// data_center.planes.release(plane_paired_model_matrix{old_model_matrices[2]});
// }
// }
} // namespace internal

31
primitive_process/src/primitive/simple/sphere.cpp

@ -1,31 +0,0 @@
#include <data/data_center.hpp>
namespace internal
{
void sphere_t::initialize(primitive_data_center_t &data_center)
{
primitive::initialize(data_center, {data_center.require_transform_block(internal::identity_model_matrix)});
}
void sphere_t::destroy()
{
primitive_data_center_t& data_center = sphere_face->data_center;
data_center.release_surface(surface_type::sphere, static_pointer_cast<subface>(sphere_face));
}
// void sphere_t::initialize(primitive_data_center_t &data_center,
// const std::vector<std::pair<internal::paired_model_matrix *, bool>> &new_model_matrices)
// {
// auto old_ptr = sphere_face.get_ptr();
// paired_model_matrix *old_model_matrices{nullptr};
// if (old_ptr != nullptr) old_model_matrices = old_ptr->model_matrices;
// auto [iter, is_new] = data_center.spheres.acquire(new_model_matrices[0].first);
// sphere_face.set_ptr(iter.operator->());
// sphere_face.set_mark(new_model_matrices[0].second);
// if (is_new) sphere_face.get_ptr()->data_center = &data_center;
// // deferred release to avoid acquiring the same just-released subface
// if (old_ptr != nullptr) data_center.spheres.release(old_model_matrices);
// }
} // namespace internal

389
shared_module/container/span.hpp

@ -0,0 +1,389 @@
#pragma once
#include <array>
#include <cstddef>
#include <limits>
#include <type_traits>
inline constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
template <typename ElementType, std::size_t Extent = dynamic_extent>
class span;
namespace detail
{
template <typename E, std::size_t S>
struct span_storage {
constexpr span_storage() noexcept = default;
constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept : ptr(p_ptr) {}
E* ptr = nullptr;
static constexpr std::size_t size = S;
};
template <typename E>
struct span_storage<E, dynamic_extent> {
constexpr span_storage() noexcept = default;
constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept : ptr(p_ptr), size(p_size) {}
E* ptr = nullptr;
std::size_t size = 0;
};
using std::void_t;
template <typename T>
using uncvref_t = typename std::remove_cv_t<std::remove_reference_t<T>>;
template <typename>
struct is_span : std::false_type {
};
template <typename T, std::size_t S>
struct is_span<span<T, S>> : std::true_type {
};
template <typename T>
static constexpr auto is_span_v = is_span<T>::value;
template <typename>
struct is_std_array : std::false_type {
};
template <typename T, std::size_t N>
struct is_std_array<std::array<T, N>> : std::true_type {
};
template <typename T>
static constexpr auto is_std_array_v = is_std_array<T>::value;
template <typename, typename = void>
struct has_size_and_data : std::false_type {
};
template <typename T>
struct has_size_and_data<T, void_t<decltype(std::size(std::declval<T>())), decltype(std::data(std::declval<T>()))>>
: std::true_type {
};
template <typename T>
static constexpr auto has_size_and_data_v = has_size_and_data<T>::value;
template <typename C, typename U = uncvref_t<C>>
struct is_container {
static constexpr bool value = !is_span_v<U> && !is_std_array_v<U> && !std::is_array_v<U> && has_size_and_data_v<C>;
};
template <typename C>
static constexpr auto is_container_v = is_container<C>::value;
template <typename T>
using remove_pointer_t = std::remove_pointer_t<T>;
template <typename, typename, typename = void>
struct is_container_element_type_compatible : std::false_type {
};
template <typename T, typename E>
struct is_container_element_type_compatible<
T,
E,
typename std::enable_if<
!std::is_same_v<std::remove_cv_t<decltype(std::data(std::declval<T>()))>, void>
&& std::is_convertible_v<remove_pointer_t<decltype(std::data(std::declval<T>()))> (*)[], E (*)[]>>::type>
: std::true_type {
};
template <typename T, typename E>
static constexpr auto is_container_element_type_compatible_v = is_container_element_type_compatible<T, E>::value;
template <typename, typename = size_t>
struct is_complete : std::false_type {
};
template <typename T>
struct is_complete<T, decltype(sizeof(T))> : std::true_type {
};
template <typename T>
static constexpr auto is_complete_v = is_complete<T>::value;
} // namespace detail
template <typename ElementType, std::size_t Extent>
class span
{
static_assert(std::is_object_v<ElementType>,
"A span's ElementType must be an object type (not a "
"reference type or void)");
static_assert(detail::is_complete_v<ElementType>,
"A span's ElementType must be a complete type (not a forward "
"declaration)");
static_assert(!std::is_abstract_v<ElementType>, "A span's ElementType cannot be an abstract class type");
using storage_type = detail::span_storage<ElementType, Extent>;
public:
// constants and types
using element_type = ElementType;
using value_type = std::remove_cv_t<ElementType>;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using pointer = element_type*;
using const_pointer = const element_type*;
using reference = element_type&;
using const_reference = const element_type&;
using iterator = pointer;
using reverse_iterator = std::reverse_iterator<iterator>;
static constexpr size_type extent = Extent;
// [span.cons], span constructors, copy, assignment, and destructor
template <std::size_t E = Extent, typename std::enable_if_t<(E == dynamic_extent || E <= 0), int> = 0>
constexpr span() noexcept
{
}
constexpr span(pointer ptr, size_type count) : storage_(ptr, count) { assert(extent == dynamic_extent || count == extent); }
constexpr span(pointer first_elem, pointer last_elem) : storage_(first_elem, last_elem - first_elem)
{
assert(extent == dynamic_extent || last_elem - first_elem == static_cast<std::ptrdiff_t>(extent));
}
template <std::size_t N,
std::size_t E = Extent,
typename = std::enable_if_t<(E == dynamic_extent || N == E)
&& detail::is_container_element_type_compatible_v<element_type (&)[N], ElementType>>>
constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N)
{
}
template <typename T,
std::size_t N,
std::size_t E = Extent,
typename = std::enable_if_t<(E == dynamic_extent || N == E)
&& detail::is_container_element_type_compatible_v<std::array<T, N>&, ElementType>>>
constexpr span(std::array<T, N>& arr) noexcept : storage_(arr.data(), N)
{
}
template <
typename T,
std::size_t N,
std::size_t E = Extent,
typename = std::enable_if_t<(E == dynamic_extent || N == E)
&& detail::is_container_element_type_compatible_v<const std::array<T, N>&, ElementType>>>
constexpr span(const std::array<T, N>& arr) noexcept : storage_(arr.data(), N)
{
}
template <typename Container,
std::size_t E = Extent,
typename = std::enable_if_t<E == dynamic_extent && detail::is_container_v<Container>
&& detail::is_container_element_type_compatible_v<Container&, ElementType>>>
constexpr span(Container& cont) : storage_(std::data(cont), std::size(cont))
{
}
template <typename Container,
std::size_t E = Extent,
typename = std::enable_if_t<E == dynamic_extent && detail::is_container_v<Container>
&& detail::is_container_element_type_compatible_v<const Container&, ElementType>>>
constexpr span(const Container& cont) : storage_(std::data(cont), std::size(cont))
{
}
constexpr span(const span& other) noexcept = default;
template <typename OtherElementType,
std::size_t OtherExtent,
typename = std::enable_if_t<(Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent)
&& std::is_convertible_v<OtherElementType (*)[], ElementType (*)[]>>>
constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept : storage_(other.data(), other.size())
{
}
~span() noexcept = default;
constexpr span& operator=(const span& other) noexcept = default;
// [span.sub], span subviews
template <std::size_t Count>
constexpr span<element_type, Count> first() const
{
assert(Count <= size());
return {data(), Count};
}
template <std::size_t Count>
constexpr span<element_type, Count> last() const
{
assert(Count <= size());
return {data() + (size() - Count), Count};
}
template <std::size_t Offset, std::size_t Count = dynamic_extent>
using subspan_return_t =
span<ElementType, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : dynamic_extent)>;
template <std::size_t Offset, std::size_t Count = dynamic_extent>
constexpr subspan_return_t<Offset, Count> subspan() const
{
assert(Offset <= size() && (Count == dynamic_extent || Offset + Count <= size()));
return {data() + Offset, Count != dynamic_extent ? Count : size() - Offset};
}
constexpr span<element_type, dynamic_extent> first(size_type count) const
{
assert(count <= size());
return {data(), count};
}
constexpr span<element_type, dynamic_extent> last(size_type count) const
{
assert(count <= size());
return {data() + (size() - count), count};
}
constexpr span<element_type, dynamic_extent> subspan(size_type offset, size_type count = dynamic_extent) const
{
assert(offset <= size() && (count == dynamic_extent || offset + count <= size()));
return {data() + offset, count == dynamic_extent ? size() - offset : count};
}
// [span.obs], span observers
constexpr size_type size() const noexcept { return storage_.size; }
constexpr size_type size_bytes() const noexcept { return size() * sizeof(element_type); }
[[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
// [span.elem], span element access
constexpr reference operator[](size_type idx) const
{
assert(idx < size());
return *(data() + idx);
}
constexpr reference front() const
{
assert(!empty());
return *data();
}
constexpr reference back() const
{
assert(!empty());
return *(data() + (size() - 1));
}
constexpr pointer data() const noexcept { return storage_.ptr; }
// [span.iterators], span iterator support
constexpr iterator begin() const noexcept { return data(); }
constexpr iterator end() const noexcept { return data() + size(); }
constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
private:
storage_type storage_{};
};
/* Deduction Guides */
template <class T, size_t N>
span(T (&)[N]) -> span<T, N>;
template <class T, size_t N>
span(std::array<T, N>&) -> span<T, N>;
template <class T, size_t N>
span(const std::array<T, N>&) -> span<const T, N>;
template <class Container>
span(Container&) -> span<std::remove_reference_t<decltype(*std::data(std::declval<Container&>()))>>;
template <class Container>
span(const Container&) -> span<const typename Container::value_type>;
template <typename ElementType, std::size_t Extent>
constexpr span<ElementType, Extent> make_span(span<ElementType, Extent> s) noexcept
{
return s;
}
template <typename T, std::size_t N>
constexpr span<T, N> make_span(T (&arr)[N]) noexcept
{
return {arr};
}
template <typename T, std::size_t N>
constexpr span<T, N> make_span(std::array<T, N>& arr) noexcept
{
return {arr};
}
template <typename T, std::size_t N>
constexpr span<const T, N> make_span(const std::array<T, N>& arr) noexcept
{
return {arr};
}
template <typename Container>
constexpr span<std::remove_reference_t<decltype(*std::data(std::declval<Container&>()))>> make_span(Container& cont)
{
return {cont};
}
template <typename Container>
constexpr span<const typename Container::value_type> make_span(const Container& cont)
{
return {cont};
}
template <typename ElementType, std::size_t Extent>
span<const std::byte, ((Extent == dynamic_extent) ? dynamic_extent : sizeof(ElementType) * Extent)> as_bytes(
span<ElementType, Extent> s) noexcept
{
return {reinterpret_cast<const std::byte*>(s.data()), s.size_bytes()};
}
template <class ElementType, size_t Extent, typename = std::enable_if_t<!std::is_const_v<ElementType>>>
span<std::byte, ((Extent == dynamic_extent) ? dynamic_extent : sizeof(ElementType) * Extent)> as_writable_bytes(
span<ElementType, Extent> s) noexcept
{
return {reinterpret_cast<std::byte*>(s.data()), s.size_bytes()};
}
template <std::size_t N, typename E, std::size_t S>
constexpr auto get(span<E, S> s) -> decltype(s[N])
{
return s[N];
}
namespace std
{
template <typename ElementType, size_t Extent>
class tuple_size<::span<ElementType, Extent>> : public integral_constant<size_t, Extent>
{
};
template <typename ElementType>
class tuple_size<::span<ElementType, ::dynamic_extent>>; // not defined
template <size_t I, typename ElementType, size_t Extent>
class tuple_element<I, ::span<ElementType, Extent>>
{
public:
static_assert(Extent != ::dynamic_extent && I < Extent, "");
using type = ElementType;
};
} // end namespace std
Loading…
Cancel
Save