Files @ r25719:14932b129f4d
Branch filter:

Location: cpp/openttd-patchpack/source/src/core/span_type.hpp

Michael Lutz
Codechange: [OSX] Use more exact enum names where introduced with the 10.12 SDK.

The enum values still have the exact same numerical values, but the 10.12
SDK introduced more explicit names (e.g. like NSEventTypeApplicationDefined
instead of NSApplicationDefined) for several enum constants.
Use them when available.
/*
 * This file is part of OpenTTD.
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 */

/** @file span_type.hpp Minimized implementation of C++20 std::span. */

#ifndef CORE_SPAN_TYPE_HPP
#define CORE_SPAN_TYPE_HPP

/* This is a partial copy/paste from https://github.com/gsl-lite/gsl-lite/blob/master/include/gsl/gsl-lite.hpp */

/* Template to check if a template variable defines size() and data(). */
template <class, class = void>
struct has_size_and_data : std::false_type{};
template <class C>
struct has_size_and_data
<
	C, std::void_t<
		decltype(std::size(std::declval<C>())),
		decltype(std::data(std::declval<C>()))>
> : std::true_type{};

/* Template to check if two elements are compatible. */
template <class, class, class = void>
struct is_compatible_element : std::false_type {};
template <class C, class E>
struct is_compatible_element
<
	C, E, std::void_t<
		decltype(std::data(std::declval<C>())),
		typename std::remove_pointer<decltype(std::data( std::declval<C&>()))>::type(*)[]>
> : std::is_convertible<typename std::remove_pointer<decltype(std::data(std::declval<C&>()))>::type(*)[], E(*)[]>{};

/* Template to check if a container is compatible. gsl-lite also includes is_array and is_std_array, but as we don't use them, they are omitted. */
template <class C, class E>
struct is_compatible_container : std::bool_constant
<
	has_size_and_data<C>::value
	&& is_compatible_element<C,E>::value
>{};

/**
 * A trimmed down version of what std::span will be in C++20.
 *
 * It is fully forwards compatible, so if this codebase switches to C++20,
 * all "span" instances can be replaced by "std::span" without loss of
 * functionality.
 *
 * Currently it only supports basic functionality:
 * - size() and friends
 * - begin() and friends
 *
 * It is meant to simplify function parameters, where we only want to walk
 * a continuous list.
 */
template<class T>
class span {
public:
	typedef T element_type;
	typedef typename std::remove_cv< T >::type value_type;

	typedef T &reference;
	typedef T *pointer;
	typedef const T &const_reference;
	typedef const T *const_pointer;

	typedef pointer iterator;
	typedef const_pointer const_iterator;

	typedef size_t size_type;
	typedef std::ptrdiff_t difference_type;

	constexpr span(pointer data_in, size_t size_in) : first(data_in), last(data_in + size_in) {}

	template<class Container, typename std::enable_if<(is_compatible_container<Container, element_type>::value), int>::type = 0>
	constexpr span(Container &list) noexcept : first(std::data(list)), last(std::data(list) + std::size(list)) {}
	template<class Container, typename std::enable_if<(std::is_const<element_type>::value && is_compatible_container<Container, element_type>::value), int>::type = 0>
	constexpr span(const Container &list) noexcept : first(std::data(list)), last(std::data(list) + std::size(list)) {}

	constexpr size_t size() const noexcept { return static_cast<size_t>( last - first ); }
	constexpr std::ptrdiff_t ssize() const noexcept { return static_cast<std::ptrdiff_t>( last - first ); }
	constexpr bool empty() const noexcept { return size() == 0; }

	constexpr iterator begin() const noexcept { return iterator(first); }
	constexpr iterator end() const noexcept { return iterator(last); }

	constexpr const_iterator cbegin() const noexcept { return const_iterator(first); }
	constexpr const_iterator cend() const noexcept { return const_iterator(last); }

private:
	pointer first;
	pointer last;
};

#endif /* CORE_SPAN_TYPE_HPP */