Add check that d_array<E> is not unsigned int or unsigned long

`std::size_t` is `unsigned int` on i686-pc-linux-gnu, but is `unsigned
long` on x86_64-pc-linux-gnu.  This mismatch allows d_array<E =
std::size_t> to be well-formed on x86_64, but trigger a duplicate
definition of operator[](E) on i686.  Add a requires() check that
forbids both types for E, so that code which would break the i686 build
is also diagnosed in the x86_64 build.
This commit is contained in:
Kp 2022-10-09 23:15:20 +00:00
parent f61db8ae7a
commit fcb6beb3e8
3 changed files with 19 additions and 5 deletions

View file

@ -60,11 +60,21 @@ class valptridx :
template <typename> template <typename>
class guarded; class guarded;
class array_base_count_type; class array_base_count_type;
using array_base_storage_type = typename std::conditional< struct array_base_storage_integral
std::is_enum<typename specialized_types::integral_type>::value, {
dcx::enumerated_array<managed_type, array_size, typename specialized_types::integral_type>, using type = std::array<managed_type, array_size>;
std::array<managed_type, array_size> };
>::type; /* Note: integral_type must be an `enum` type, but
* `requires(std::is_enum<integral_type>::value)` cannot be checked
* here, because the name `array_base_storage_enum<integral_type>` may be
* formed for non-enum types, but the internal type `type` will not be
* used in those cases.
*/
template <typename integral_type>
struct array_base_storage_enum
{
using type = dcx::enumerated_array<managed_type, array_size, integral_type>;
};
protected: protected:
using const_pointer_type = const managed_type *; using const_pointer_type = const managed_type *;
using const_reference_type = const managed_type &; using const_reference_type = const managed_type &;
@ -75,6 +85,7 @@ protected:
*/ */
using typename specialized_types::integral_type; using typename specialized_types::integral_type;
using index_type = integral_type; // deprecated; should be dedicated UDT using index_type = integral_type; // deprecated; should be dedicated UDT
using array_base_storage_type = typename std::conditional<std::is_integral<integral_type>::value, array_base_storage_integral, array_base_storage_enum<integral_type>>::type::type;
public: public:
class array_managed_type; class array_managed_type;

View file

@ -24,6 +24,7 @@ namespace dcx {
* Other types for E are not likely to be useful, but are not blocked. * Other types for E are not likely to be useful, but are not blocked.
*/ */
template <typename T, std::size_t N, typename E> template <typename T, std::size_t N, typename E>
requires(!std::is_same<unsigned, E>::value && !std::is_same<unsigned long, E>::value)
struct enumerated_array : std::array<T, N> struct enumerated_array : std::array<T, N>
{ {
using base_type = std::array<T, N>; using base_type = std::array<T, N>;

View file

@ -7,10 +7,12 @@
#pragma once #pragma once
#include <cstddef> #include <cstddef>
#include <type_traits>
namespace dcx { namespace dcx {
template <typename T, std::size_t N, typename E> template <typename T, std::size_t N, typename E>
requires(!std::is_same<unsigned, E>::value && !std::is_same<unsigned long, E>::value)
struct enumerated_array; struct enumerated_array;
} }