concepts: Use the std::contiguous_iterator concept

This also covers std::span, which does not have a const iterator.

Also renames IsSTLContainer to IsContiguousContainer to explicitly convey its semantics.
This commit is contained in:
Morph 2022-10-26 00:41:54 -04:00
parent d8e3380ea5
commit 8b4d5aeb4f
3 changed files with 10 additions and 20 deletions

View file

@ -3,24 +3,14 @@
#pragma once #pragma once
#include <iterator>
#include <type_traits> #include <type_traits>
namespace Common { namespace Common {
// Check if type is like an STL container // Check if type satisfies the ContiguousContainer named requirement.
template <typename T> template <typename T>
concept IsSTLContainer = requires(T t) { concept IsContiguousContainer = std::contiguous_iterator<typename T::iterator>;
typename T::value_type;
typename T::iterator;
typename T::const_iterator;
// TODO(ogniK): Replace below is std::same_as<void> when MSVC supports it.
t.begin();
t.end();
t.cbegin();
t.cend();
t.data();
t.size();
};
// TODO: Replace with std::derived_from when the <concepts> header // TODO: Replace with std::derived_from when the <concepts> header
// is available on all supported platforms. // is available on all supported platforms.

View file

@ -209,8 +209,8 @@ public:
/** /**
* Helper function which deduces the value type of a contiguous STL container used in ReadSpan. * Helper function which deduces the value type of a contiguous STL container used in ReadSpan.
* If T is not a contiguous STL container as defined by the concept IsSTLContainer, this calls * If T is not a contiguous container as defined by the concept IsContiguousContainer, this
* ReadObject and T must be a trivially copyable object. * calls ReadObject and T must be a trivially copyable object.
* *
* See ReadSpan for more details if T is a contiguous container. * See ReadSpan for more details if T is a contiguous container.
* See ReadObject for more details if T is a trivially copyable object. * See ReadObject for more details if T is a trivially copyable object.
@ -223,7 +223,7 @@ public:
*/ */
template <typename T> template <typename T>
[[nodiscard]] size_t Read(T& data) const { [[nodiscard]] size_t Read(T& data) const {
if constexpr (IsSTLContainer<T>) { if constexpr (IsContiguousContainer<T>) {
using ContiguousType = typename T::value_type; using ContiguousType = typename T::value_type;
static_assert(std::is_trivially_copyable_v<ContiguousType>, static_assert(std::is_trivially_copyable_v<ContiguousType>,
"Data type must be trivially copyable."); "Data type must be trivially copyable.");
@ -235,8 +235,8 @@ public:
/** /**
* Helper function which deduces the value type of a contiguous STL container used in WriteSpan. * Helper function which deduces the value type of a contiguous STL container used in WriteSpan.
* If T is not a contiguous STL container as defined by the concept IsSTLContainer, this calls * If T is not a contiguous STL container as defined by the concept IsContiguousContainer, this
* WriteObject and T must be a trivially copyable object. * calls WriteObject and T must be a trivially copyable object.
* *
* See WriteSpan for more details if T is a contiguous container. * See WriteSpan for more details if T is a contiguous container.
* See WriteObject for more details if T is a trivially copyable object. * See WriteObject for more details if T is a trivially copyable object.
@ -249,7 +249,7 @@ public:
*/ */
template <typename T> template <typename T>
[[nodiscard]] size_t Write(const T& data) const { [[nodiscard]] size_t Write(const T& data) const {
if constexpr (IsSTLContainer<T>) { if constexpr (IsContiguousContainer<T>) {
using ContiguousType = typename T::value_type; using ContiguousType = typename T::value_type;
static_assert(std::is_trivially_copyable_v<ContiguousType>, static_assert(std::is_trivially_copyable_v<ContiguousType>,
"Data type must be trivially copyable."); "Data type must be trivially copyable.");

View file

@ -304,7 +304,7 @@ public:
*/ */
template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>> template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>>
std::size_t WriteBuffer(const T& data, std::size_t buffer_index = 0) const { std::size_t WriteBuffer(const T& data, std::size_t buffer_index = 0) const {
if constexpr (Common::IsSTLContainer<T>) { if constexpr (Common::IsContiguousContainer<T>) {
using ContiguousType = typename T::value_type; using ContiguousType = typename T::value_type;
static_assert(std::is_trivially_copyable_v<ContiguousType>, static_assert(std::is_trivially_copyable_v<ContiguousType>,
"Container to WriteBuffer must contain trivially copyable objects"); "Container to WriteBuffer must contain trivially copyable objects");