Fix OS X clang build

OS X still uses clang-14, which lacks sufficient std::ranges support for
recent Rebirth changes.

- Rewrite uses of std::ranges::SYMBOL to ranges::SYMBOL
- Add a stub header that, on gcc, provides for each SYMBOL a statement
  `using std::ranges::SYMBOL;`, to delegate back to the standard library
  implementation.
- On clang, define a minimal implementation of the required symbols,
  without constraint enforcement.  Compile-testing with gcc will catch
  constraint violations.

Once OS X clang ships a standard library with the required features,
this stub header will be removed and the uses changed back to their full
names.
This commit is contained in:
Kp 2022-10-31 00:51:32 +00:00
parent 3567a7bc98
commit 3d5de92058
31 changed files with 222 additions and 71 deletions

View File

@ -2682,25 +2682,59 @@ constexpr literal_as_type<T, v...> operator""_literal_as_type();
self.successful_flags['CXXFLAGS'].append('-Wno-gnu-string-literal-operator-template')
@_custom_test
def check_have_std_ranges(self,context,_successflags={'CPPDEFINES' : ['_LIBCPP_ENABLE_EXPERIMENTAL']}):
def check_have_std_ranges(self,context,_testflags={'CPPDEFINES' : ['_LIBCPP_ENABLE_EXPERIMENTAL']}):
text = '''
#include <algorithm>
#include "backports-ranges.h"
struct test_borrowed_range {};
template <>
constexpr bool std::ranges::enable_borrowed_range<test_borrowed_range> = true;
template <typename R>
requires(std::ranges::range<R>)
static void requires_range(R &) {}
template <typename R>
requires(std::ranges::borrowed_range<R>)
static void requires_borrowed_range(R &&) {}
'''
main = '''
int a[3]{1, 2, 3};
return std::ranges::find(a, argc) == a;
int b[2]{4, 5};
const ranges::subrange c(b);
const ranges::subrange<int *> c2(b);
(void)c2;
const auto m = [](int i) { return i * 2; };
(void)(ranges::find(a, argc) == a);
(void)(ranges::find(a, argc, m) == a);
(void)(ranges::find(std::ranges::begin(b), std::ranges::end(b), argc) == a);
(void)(ranges::find(std::ranges::begin(b), std::ranges::end(b), argc, m) == a);
const auto predicate = [](int i) { return i == 3; };
(void)(ranges::find_if(b, predicate) == a);
(void)(ranges::find_if(std::ranges::begin(b), std::ranges::end(b), predicate) == a);
requires_range(a);
requires_borrowed_range(a);
return 0;
'''
if self.Compile(context, text=text, main=main, msg='whether C++ compiler provides std::ranges by default'):
return
# As a special case, put this define in the command-line instead of
# allowing it to be moved to `dxxsconf.h`. This define must be in
# effect before the C++ compiler sees a `#include` of any system
# headers that conditionally define experimental functionality.
# Placing the define on the command line ensures that. If the
# preprocessor definition were in `dxxsconf.h`, then some files might
# include the system header before including the definition.
if self.Compile(context, text=text, main=main, msg='whether C++ compiler provides std::ranges with -D_LIBCPP_ENABLE_EXPERIMENTAL', testflags=_successflags):
self.successful_flags['CPPDEFINES'].extend(*_successflags.items())
# std::ranges is a C++20 feature.
# gcc first shipped std::ranges in gcc-10.1 [1], which was released on
# 2020-05-07 [2].
# clang shipped incomplete std::ranges behind a preprocessor guard in
# clang-14 [3], which was released on 2022-03-25 [4].
#
# As of this writing, Apple clang is still clang-14, and so does not
# support all needed std::ranges features, even with the preprocessor
# guard defined. Try to work around this by bundling an implementation
# sufficient to cover Rebirth's needs.
#
# [1]: https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#table.cxx20_features
# [2]: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=6e6e3f144a33ae504149dc992453b4f6dea12fdb
# [3]: https://libcxx.llvm.org/Status/Ranges.html
# [4]: https://discourse.llvm.org/t/llvm-14-0-0-release/61224
if self.Compile(context, text=text, main=main, msg='whether C++ compiler can use bundled ranges support with -D_LIBCPP_ENABLE_EXPERIMENTAL', testflags=_testflags):
return
raise SCons.Errors.StopError("C++ compiler does not support std::ranges.")

View File

@ -33,6 +33,7 @@
#include "dsx-ns.h"
#include "compiler-range_for.h"
#include <array>
#include "backports-ranges.h"
namespace dcx {
@ -512,7 +513,7 @@ window_event_result key_handler(const SDL_KeyboardEvent *const kevent)
//=====================================================
const auto re = key_properties.rend();
const auto &&fi = std::ranges::find(key_properties.rbegin(), re, event_keysym, &key_props::sym);
const auto &&fi = ranges::find(key_properties.rbegin(), re, event_keysym, &key_props::sym);
if (fi == re)
return window_event_result::ignored;
unsigned keycode = std::distance(key_properties.begin(), std::next(fi).base());

View File

@ -89,7 +89,7 @@ void RBAInit()
if (s_cd && CD_INDRIVE(SDL_CDStatus(s_cd)))
{
const auto &&r = partial_const_range(s_cd->track, static_cast<unsigned>(s_cd->numtracks));
if (std::ranges::find(r, SDL_AUDIO_TRACK, &SDL_CDtrack::type) != r.end())
if (ranges::find(r, SDL_AUDIO_TRACK, &SDL_CDtrack::type) != r.end())
{
initialised = 1;
RBAList();

View File

@ -14,6 +14,7 @@
#include "fwd-partial_range.h"
#include <memory>
#include "dxxsconf.h"
#include "backports-ranges.h"
/* If no value was specified for DXX_PARTIAL_RANGE_MINIMIZE_ERROR_TYPE,
* then define it to true for NDEBUG builds and false for debug builds.

View File

@ -19,6 +19,7 @@ typedef char file_extension_t[5];
#include "dsx-ns.h"
#include "fwd-partial_range.h"
#include <array>
#include "backports-ranges.h"
namespace dcx {
@ -79,11 +80,11 @@ typedef PHYSFSX_counted_list_template<PHYSFS_list_deleter> PHYSFSX_counted_list;
[[nodiscard]]
__attribute_nonnull()
PHYSFSX_uncounted_list PHYSFSX_findFiles(const char *path, std::ranges::subrange<const file_extension_t *> exts);
PHYSFSX_uncounted_list PHYSFSX_findFiles(const char *path, ranges::subrange<const file_extension_t *> exts);
[[nodiscard]]
__attribute_nonnull()
PHYSFSX_uncounted_list PHYSFSX_findabsoluteFiles(const char *path, const char *realpath, std::ranges::subrange<const file_extension_t *> exts);
PHYSFSX_uncounted_list PHYSFSX_findabsoluteFiles(const char *path, const char *realpath, ranges::subrange<const file_extension_t *> exts);
}
#endif

View File

@ -36,7 +36,6 @@
#include "vecmat.h"
#include "byteutil.h"
#ifdef __cplusplus
#include <stdexcept>
#include "u_mem.h"
#include "pack.h"
@ -44,6 +43,7 @@
#include "fwd-partial_range.h"
#include <array>
#include <memory>
#include "backports-ranges.h"
#ifdef DXX_CONSTANT_TRUE
#define _DXX_PHYSFS_CHECK_SIZE_CONSTANT(S,v) DXX_CONSTANT_TRUE((S) > (v))
@ -424,7 +424,7 @@ typedef char file_extension_t[5];
[[nodiscard]]
__attribute_nonnull()
int PHYSFSX_checkMatchingExtension(const char *filename, const std::ranges::subrange<const file_extension_t *> range);
int PHYSFSX_checkMatchingExtension(const char *filename, const ranges::subrange<const file_extension_t *> range);
enum class physfs_search_path : int
{
@ -502,5 +502,3 @@ RAIIPHYSFS_ComputedPathMount make_PHYSFSX_ComputedPathMount(const char *const na
}
#endif
#endif

View File

@ -0,0 +1,117 @@
/*
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
* It is copyright by its individual contributors, as recorded in the
* project's Git history. See COPYING.txt at the top level for license
* terms and a link to the Git history.
*/
/*
* std::ranges is a C++20 feature.
*
* gcc-10.1 (released 2020-05-07) shipped std::ranges support.
*
* clang-14 (released 2022-03-25) lacks sufficient std::ranges support, and
* requires a preprocessor symbol to unlock the parts it provides.
*
* clang-15 (released 2022-09-06) defines sufficient std::ranges support, but
* is still incomplete, and still requires a preprocessor symbol to unlock
* them.
*
* clang-14 is currently standard on OS X.
*
* When Rebirth is built with clang, this header provides a minimal
* implementation to allow calling code to use those features, but does not
* attempt to provide the constraints that a standards-conforming
* implementation would provide.
*
* When Rebirth is built with gcc, this header provides `using` declarations to
* pull in the compiler's `std::ranges` implementation, which will include the
* standards-conforming constraints.
*/
#pragma once
#include <algorithm>
#include <ranges>
namespace ranges {
#ifdef __clang__
template <typename iterator, typename sentinel = iterator>
class subrange
{
iterator b;
sentinel e;
public:
subrange(iterator b, sentinel e) :
b(b), e(e)
{
}
subrange(auto &r) :
b(std::ranges::begin(r)), e(std::ranges::end(r))
{
}
iterator begin() const { return b; }
sentinel end() const { return e; }
};
subrange(auto &r) -> subrange<decltype(std::ranges::begin(r)), decltype(std::ranges::end(r))>;
template <typename IB, typename V>
requires(
requires(IB b, V v) {
*b == v;
}
)
auto find(IB b, auto e, V v)
{
for (; b != e; ++b)
if (*b == v)
break;
return b;
}
auto find(auto b, auto e, auto v, auto project)
{
for (; b != e; ++b)
if (std::invoke(project, *b) == v)
break;
return b;
}
auto find(auto &r, auto v)
{
return find(std::ranges::begin(r), std::ranges::end(r), v);
}
template <typename R, typename P>
requires(
requires(R &r, P p) {
std::invoke(p, *std::ranges::begin(r));
}
)
auto find(R &r, auto v, P project)
{
return find(std::ranges::begin(r), std::ranges::end(r), v, project);
}
auto find_if(auto b, auto e, auto predicate)
{
for (; b != e; ++b)
if (predicate(*b))
break;
return b;
}
auto find_if(auto &r, auto predicate)
{
return find_if(std::ranges::begin(r), std::ranges::end(r), predicate);
}
#else
using std::ranges::subrange;
using std::ranges::find;
using std::ranges::find_if;
#endif
}

View File

@ -10,7 +10,6 @@
#include "dxxsconf.h"
#include "partial_range.h"
#include "ephemeral_range.h"
#include <ranges>
#include <tuple>
#include <type_traits>

View File

@ -65,7 +65,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#include <array>
#ifdef dsx
#include <ranges>
#include "backports-ranges.h"
#endif
namespace dcx {
@ -526,7 +526,7 @@ void multi_disconnect_player(playernum_t);
namespace dsx {
void multi_initiate_save_game();
void multi_initiate_restore_game();
void multi_execute_save_game(d_game_unique_state::save_slot slot, const d_game_unique_state::savegame_description &desc, std::ranges::subrange<const player *> player_range);
void multi_execute_save_game(d_game_unique_state::save_slot slot, const d_game_unique_state::savegame_description &desc, ranges::subrange<const player *> player_range);
#if defined(DXX_BUILD_DESCENT_I)
static inline void multi_send_got_flag (playernum_t) {}
#elif defined(DXX_BUILD_DESCENT_II)

View File

@ -75,7 +75,7 @@ static keypad_input_line_t::const_iterator find_fake_comma(keypad_input_line_t::
const auto is_fake_comma = [](const char c) {
return !c || static_cast<uint8_t>(c) == 179;
};
return std::ranges::find_if(i, e, is_fake_comma);
return ranges::find_if(i, e, is_fake_comma);
}
template <bool append, char eor>
@ -84,7 +84,7 @@ static keypad_input_line_t::const_iterator set_row(keypad_input_line_t::const_it
const auto oe = r.end();
auto ob = r.begin();
if (append)
ob = std::ranges::find(ob, oe, 0);
ob = ranges::find(ob, oe, 0);
auto comma0 = find_fake_comma(i, e);
if (comma0 == e)
/* Start not found */

View File

@ -687,13 +687,13 @@ static std::pair<icsegidx_t, d_unique_buddy_state::Escort_goal_reachability> exi
return vcsegptr(s)->special == segment_special::fuelcen;
};
const auto &&rb = partial_const_range(bfs_list, length);
const auto &&i = std::ranges::find_if(rb, predicate);
const auto &&i = ranges::find_if(rb, predicate);
if (i != rb.end())
return {*i, d_unique_buddy_state::Escort_goal_reachability::reachable};
}
{
const auto &&rh = make_range(vcsegptridx);
const auto &&i = std::ranges::find(rh, segment_special::fuelcen, &shared_segment::special);
const auto &&i = ranges::find(rh, segment_special::fuelcen, &shared_segment::special);
if (i != rh.end())
return {*i, d_unique_buddy_state::Escort_goal_reachability::unreachable};
}

View File

@ -564,7 +564,7 @@ static int med_copy_group(const unsigned delta_flag, const vmsegptridx_t base_se
auto gb = GroupList[current_group].segments.begin();
auto ge = GroupList[current_group].segments.end();
auto gp = Groupsegp[current_group];
const auto &&gi = std::ranges::find_if(gb, ge, [gp](const segnum_t segnum) { return vcsegptr(segnum) == gp; });
const auto &&gi = ranges::find_if(gb, ge, [gp](const segnum_t segnum) { return vcsegptr(segnum) == gp; });
int gs_index = (gi == ge) ? 0 : std::distance(gb, gi);
GroupList[new_current_group] = GroupList[current_group];

View File

@ -113,7 +113,7 @@ static void con_scrub_markup(const std::span<char> buffer)
{
const auto b = buffer.begin();
const auto e = buffer.end();
const auto &&i = std::ranges::find_if(b, e, [](const char c) { return c == CC_COLOR || c == CC_LSPACING || c == CC_UNDERLINE; });
const auto &&i = ranges::find_if(b, e, [](const char c) { return c == CC_COLOR || c == CC_LSPACING || c == CC_UNDERLINE; });
if (i == e)
return;
auto p1 = i;

View File

@ -113,7 +113,7 @@ static void digi_kill_sound(sound_object &s)
static std::pair<sound_objects_t::iterator, sound_objects_t::iterator> find_sound_object_flags0(sound_objects_t &SoundObjects)
{
const auto eso = SoundObjects.end();
const auto &&i = std::ranges::find(SoundObjects.begin(), eso, 0, &sound_object::flags);
const auto &&i = ranges::find(SoundObjects.begin(), eso, 0, &sound_object::flags);
return {i, eso};
}

View File

@ -616,7 +616,7 @@ static void write_trigger_text(PHYSFS_File *my_file)
// Find which wall this trigger is connected to.
const auto &&we = vcwallptr.end();
const auto &&wi = std::ranges::find(vcwallptr.begin(), we, i, &wall::trigger);
const auto &&wi = ranges::find(vcwallptr.begin(), we, i, &wall::trigger);
if (wi == we)
err_printf(my_file, "Error: Trigger %i is not connected to any wall, so it can never be triggered.", underlying_value(i));
else

View File

@ -789,7 +789,7 @@ static vmsegptridx_t choose_drop_segment(fvmsegptridx &vmsegptridx, fvcvertptr &
std::optional<vmsegptridx_t> fallback_drop;
for (const unsigned candidate_depth : xrange(std::uniform_int_distribution(net_drop_max_depth_lower + 0u, net_drop_max_depth_upper + 0u)(mrd), net_drop_min_depth, xrange_descending()))
{
for (const auto pnum : std::ranges::subrange(candidate_drop_players.begin(), end_drop_players))
for (const auto pnum : ranges::subrange(candidate_drop_players.begin(), end_drop_players))
{
auto &plr = *vcplayerptr(pnum);
auto &plrobj = *vcobjptr(plr.objnum);

View File

@ -667,7 +667,7 @@ void init_all_matcens(void)
station.Enabled = 0;
station.Disable_time = 0;
// Make sure this fuelcen is pointed at by a matcen.
if (std::ranges::find(robot_range, i, &matcen_info::fuelcen_num) == robot_range.end())
if (ranges::find(robot_range, i, &matcen_info::fuelcen_num) == robot_range.end())
{
station.Lives = 0;
LevelError("Station %i has type robotmaker, but no robotmaker uses it; ignoring.", underlying_value(i));

View File

@ -2269,7 +2269,7 @@ static std::pair<d_flickering_light_state::Flickering_light_array_t::iterator, d
return f.segnum == segnum && f.sidenum == sidenum; //found it!
};
const auto &&pe = pr.end();
return {std::ranges::find_if(pr.begin(), pe, predicate), pe};
return {ranges::find_if(pr.begin(), pe, predicate), pe};
}
static void update_flicker(d_flickering_light_state &fls, const vmsegidx_t segnum, const sidenum_t sidenum, const fix timer)

View File

@ -1554,7 +1554,7 @@ static window_event_result HandleTestKey(const d_level_shared_robot_info_state &
}};
struct briefing_menu : passive_newmenu
{
briefing_menu(grs_canvas &canvas, const std::ranges::subrange<newmenu_item *> items) :
briefing_menu(grs_canvas &canvas, const ranges::subrange<newmenu_item *> items) :
passive_newmenu(menu_title{nullptr}, menu_subtitle{"Briefing to play?"}, menu_filename{nullptr}, tiny_mode_flag::normal, tab_processing_flag::ignore, adjusted_citem::create(items, 0), canvas)
{
}

View File

@ -1198,7 +1198,7 @@ static int load_game_data(
{
const auto i = (*iter).get_unchecked_index();
// Find which wall this trigger is connected to.
const auto &&w = std::ranges::find(wr, i, &wall::trigger);
const auto &&w = ranges::find(wr, i, &wall::trigger);
if (w == wr.end())
{
remove_trigger_num(Triggers, Walls.vmptr, i);

View File

@ -251,7 +251,7 @@ enum class select_dir_flag : uint8_t
};
__attribute_nonnull()
static int select_file_recursive(const menu_title title, const std::array<char, PATH_MAX> &orig_path, const std::ranges::subrange<const file_extension_t *> &ext_list, select_dir_flag select_dir, ntstring<PATH_MAX - 1> &userdata);
static int select_file_recursive(const menu_title title, const std::array<char, PATH_MAX> &orig_path, const ranges::subrange<const file_extension_t *> &ext_list, select_dir_flag select_dir, ntstring<PATH_MAX - 1> &userdata);
static window_event_result get_absolute_path(ntstring<PATH_MAX - 1> &full_path, const char *rel_path)
{
@ -1264,7 +1264,7 @@ void screen_resolution_menu::check_apply_preset_resolution() const
return 0;
return ni.value;
};
const auto &&i = std::ranges::find_if(r, predicate);
const auto &&i = ranges::find_if(r, predicate);
if (i == r.end())
return;
const auto requested_mode = std::get<0>(*i);
@ -2216,23 +2216,23 @@ struct browser_storage
{
struct target_path_not_mounted {};
// List of file extensions we're looking for (if looking for a music file many types are possible)
const std::ranges::subrange<const file_extension_t *> ext_range;
const ranges::subrange<const file_extension_t *> ext_range;
const select_dir_flag select_dir; // Allow selecting the current directory (e.g. for Jukebox level song directory)
physfsx_mounted_path view_path; // The absolute path we're currently looking at
string_array_t list;
browser_storage(const char *orig_path, const std::ranges::subrange<const file_extension_t *> &ext_range, const select_dir_flag select_dir, const char *const sep) :
browser_storage(const char *orig_path, const ranges::subrange<const file_extension_t *> &ext_range, const select_dir_flag select_dir, const char *const sep) :
ext_range(ext_range), select_dir(select_dir),
/* view_path is trivially constructed, then properly initialized as
* a side effect of preparing the string list */
list(construct_string_list(orig_path, view_path, ext_range, select_dir, sep))
{
}
static string_array_t construct_string_list(const char *orig_path, physfsx_mounted_path &view_path, const std::ranges::subrange<const file_extension_t *> &r, const select_dir_flag select_dir, const char *const sep);
static string_array_t construct_string_list(const char *orig_path, physfsx_mounted_path &view_path, const ranges::subrange<const file_extension_t *> &r, const select_dir_flag select_dir, const char *const sep);
};
struct browser : browser_storage, listbox
{
browser(const char *orig_path, menu_title title, const std::ranges::subrange<const file_extension_t *> &r, const select_dir_flag select_dir, const char *const sep, ntstring<PATH_MAX - 1> &userdata) :
browser(const char *orig_path, menu_title title, const ranges::subrange<const file_extension_t *> &r, const select_dir_flag select_dir, const char *const sep, ntstring<PATH_MAX - 1> &userdata) :
browser_storage(orig_path, r, select_dir, sep),
listbox(0, list.pointer().size(), &list.pointer().front(), title, grd_curscreen->sc_canvas, 1),
userdata(userdata)
@ -2245,7 +2245,7 @@ struct browser : browser_storage, listbox
struct list_directory_context
{
string_array_t &string_list;
const std::ranges::subrange<const file_extension_t *> ext_range;
const ranges::subrange<const file_extension_t *> ext_range;
const std::array<char, PATH_MAX> &path;
};
@ -2280,7 +2280,7 @@ window_event_result browser::callback_handler(const d_event &event, window_event
}};
struct drive_letter_menu : passive_newmenu
{
drive_letter_menu(grs_canvas &canvas, const std::ranges::subrange<newmenu_item *> items) :
drive_letter_menu(grs_canvas &canvas, const ranges::subrange<newmenu_item *> items) :
passive_newmenu(menu_title{nullptr}, menu_subtitle{"Enter drive letter"}, menu_filename{nullptr}, tiny_mode_flag::normal, tab_processing_flag::ignore, adjusted_citem::create(items, 0), canvas)
{
}
@ -2364,7 +2364,7 @@ window_event_result browser::callback_handler(const d_event &event, window_event
return window_event_result::ignored;
}
static int select_file_recursive(const menu_title title, const std::array<char, PATH_MAX> &orig_path_storage, const std::ranges::subrange<const file_extension_t *> &ext_range, const select_dir_flag select_dir, ntstring<PATH_MAX - 1> &userdata)
static int select_file_recursive(const menu_title title, const std::array<char, PATH_MAX> &orig_path_storage, const ranges::subrange<const file_extension_t *> &ext_range, const select_dir_flag select_dir, ntstring<PATH_MAX - 1> &userdata)
{
const auto sep = PHYSFS_getDirSeparator();
auto orig_path = orig_path_storage.data();
@ -2383,7 +2383,7 @@ static int select_file_recursive(const menu_title title, const std::array<char,
}
}
string_array_t browser_storage::construct_string_list(const char *orig_path, physfsx_mounted_path &view_path, const std::ranges::subrange<const file_extension_t *> &ext_range, const select_dir_flag select_dir, const char *const sep)
string_array_t browser_storage::construct_string_list(const char *orig_path, physfsx_mounted_path &view_path, const ranges::subrange<const file_extension_t *> &ext_range, const select_dir_flag select_dir, const char *const sep)
{
view_path.path.front() = 0;
// Set the viewing directory to orig_path, or some parent of it

View File

@ -879,7 +879,7 @@ static void set_briefing_filename(d_fname &f, const char *const v)
auto a = [](char c) {
return !c || c == '.';
};
const auto &&i = std::ranges::find_if(v, next(v, f.size() - sizeof(tex)), a);
const auto &&i = ranges::find_if(v, next(v, f.size() - sizeof(tex)), a);
std::size_t d = std::distance(v, i);
set_briefing_filename(f, {v, d});
}
@ -889,7 +889,7 @@ static void record_briefing(d_fname &f, std::array<char, PATH_MAX> &buf)
const auto v = get_value(buf.data());
if (!v)
return;
const std::size_t d = std::distance(v, std::ranges::find_if(v, buf.end(), null_or_space));
const std::size_t d = std::distance(v, ranges::find_if(v, buf.end(), null_or_space));
if (d >= FILENAME_LEN)
return;
{
@ -1046,7 +1046,7 @@ static const char *load_mission(const mle *const mission)
if (!PHYSFSX_fgets(buf, mfile))
break;
auto &line = buf.line();
const auto &&s = std::ranges::find_if(line, null_or_space);
const auto &&s = ranges::find_if(line, null_or_space);
if (i.copy_if(line, std::distance(line.begin(), s)))
{
++level_names_loaded;
@ -1092,7 +1092,7 @@ static const char *load_mission(const mle *const mission)
auto a = [](char c) {
return isspace(static_cast<unsigned>(c));
};
const auto &&s = std::ranges::find_if(lb, t, a);
const auto &&s = ranges::find_if(lb, t, a);
if (name.copy_if(line, std::distance(lb, s)))
{
unsigned long ls = strtoul(t + 1, &ip, 10);

View File

@ -476,7 +476,7 @@ void morph_start(d_level_unique_morph_object_state &LevelUniqueMorphObjectState,
auto &mo = *pmo.get();
return mo.obj->type == OBJ_NONE || mo.obj->signature != mo.Morph_sig;
};
const auto moi = std::ranges::find_if(mob, moe, mop);
const auto moi = ranges::find_if(mob, moe, mop);
if (moi == moe) //no free slots
return;

View File

@ -3463,7 +3463,7 @@ texture_index find_goal_texture(const d_level_unique_tmap_info_state &LevelUniqu
return (i.flags & tmi_flag);
};
const auto begin = r.begin();
const auto idx = std::distance(begin, std::ranges::find_if(begin, r.end(), predicate));
const auto idx = std::distance(begin, ranges::find_if(begin, r.end(), predicate));
return idx;
}
@ -4909,7 +4909,7 @@ void multi_initiate_save_game()
multi_execute_save_game(slot, desc, player_range);
}
void multi_execute_save_game(const d_game_unique_state::save_slot slot, const d_game_unique_state::savegame_description &desc, const std::ranges::subrange<const player *> player_range)
void multi_execute_save_game(const d_game_unique_state::save_slot slot, const d_game_unique_state::savegame_description &desc, const ranges::subrange<const player *> player_range)
{
// Make a unique game id
fix game_id;

View File

@ -3047,7 +3047,7 @@ static unsigned net_udp_send_request(void)
// game, non-zero if there is some problem.
auto b = Netgame.players.begin();
auto e = Netgame.players.end();
const auto &&i = std::ranges::find_if(b, e, [](const netplayer_info &ni) { return ni.connected != player_connection_status::disconnected; });
const auto &&i = ranges::find_if(b, e, [](const netplayer_info &ni) { return ni.connected != player_connection_status::disconnected; });
if (i == e)
{
Assert(false);
@ -3110,7 +3110,7 @@ static void net_udp_process_game_info_light(const uint8_t *data, uint_fast32_t,
menu->num_active_udp_changed = 1;
auto r = partial_range(menu->Active_udp_games, menu->num_active_udp_games);
const auto &&i = std::ranges::find_if(r, [&recv_game](const UDP_netgame_info_lite &g) { return !d_stricmp(g.game_name.data(), recv_game.game_name.data()) && g.GameID == recv_game.GameID; });
const auto &&i = ranges::find_if(r, [&recv_game](const UDP_netgame_info_lite &g) { return !d_stricmp(g.game_name.data(), recv_game.game_name.data()) && g.GameID == recv_game.GameID; });
if (i == menu->Active_udp_games.end())
{
return;
@ -5671,7 +5671,7 @@ void net_udp_noloss_process_queue(fix64 time)
{
const auto b = UDP_mdata_queue.begin();
const auto e = std::next(b, UDP_mdata_queue_highest);
const auto &&first_used_entry = std::ranges::find_if(b, e, [](const UDP_mdata_store &m) { return m.used; });
const auto &&first_used_entry = ranges::find_if(b, e, [](const UDP_mdata_store &m) { return m.used; });
if (first_used_entry != b)
{
std::move(first_used_entry, e, b);

View File

@ -688,13 +688,13 @@ static void newmenu_scroll(newmenu *const menu, const int amount)
const auto predicate = [](const newmenu_item &n) {
return n.type != nm_type::text;
};
const auto &&first = std::ranges::find_if(range, predicate);
const auto &&first = ranges::find_if(range, predicate);
if (first == range.end())
/* This should not happen. If every entry is of type `nm_type::text`,
* then `menu->all_text` should have been true.
*/
return;
const auto &&rlast = std::ranges::find_if(std::reverse_iterator(range.end()), std::reverse_iterator(first), predicate).base();
const auto &&rlast = ranges::find_if(std::reverse_iterator(range.end()), std::reverse_iterator(first), predicate).base();
/* `first == rlast` should not happen, since that would mean that
* there are no elements in `range` for which `predicate` is true.
* If there are no such elements, then `first == range.end()` should

View File

@ -1271,7 +1271,7 @@ namespace {
* pointer to end(). The caller must check that the first unused
* element is not end().
*/
static std::array<std::array<hli, MAX_MISSIONS>::pointer, 2> find_hli_entry(const std::ranges::subrange<hli *> r, const Mission_path &m)
static std::array<std::array<hli, MAX_MISSIONS>::pointer, 2> find_hli_entry(const ranges::subrange<hli *> r, const Mission_path &m)
{
const auto mission_filename = m.filename;
const auto mission_length = std::distance(mission_filename, m.path.end());
@ -1286,7 +1286,7 @@ static std::array<std::array<hli, MAX_MISSIONS>::pointer, 2> find_hli_entry(cons
const auto &&a = [p = &*mission_filename](const hli &h) {
return !d_stricmp(h.Shortname.data(), p);
};
const auto &&i = std::ranges::find_if(r, a);
const auto &&i = ranges::find_if(r, a);
return {{&*i, r.end()}};
}
}

View File

@ -1040,7 +1040,7 @@ static bool compare_children(fvcvertptr &vcvertptr, const vms_vector &Viewer_eye
//short the children of segment to render in the correct order
//returns non-zero if swaps were made
using sort_child_array_t = per_side_array<sidenum_t>;
static void sort_seg_children(fvcvertptr &vcvertptr, const vms_vector &Viewer_eye, const vcsegptridx_t seg, const std::ranges::subrange<sort_child_array_t::iterator> &r)
static void sort_seg_children(fvcvertptr &vcvertptr, const vms_vector &Viewer_eye, const vcsegptridx_t seg, const ranges::subrange<sort_child_array_t::iterator> &r)
{
//for each child, compare with other children and see if order matters
//if order matters, fix if wrong
@ -1400,7 +1400,7 @@ static void build_segment_list(render_state_t &rstate, const vms_vector &Viewer_
continue;
//now order the sides in some magical way
const auto &&child_range = std::ranges::subrange(child_begin, child_iter);
const auto &&child_range = ranges::subrange(child_begin, child_iter);
sort_seg_children(vcvertptr, Viewer_eye, seg, child_range);
project_list(seg->verts);
range_for (const auto siden, child_range)

View File

@ -290,7 +290,7 @@ void scores_maybe_add_player()
const auto end_score_stats = std::end(scores.stats);
/* Find the position at which the player's score should be placed.
*/
const auto &&iter_position = std::ranges::find_if(begin_score_stats, end_score_stats, predicate);
const auto &&iter_position = ranges::find_if(begin_score_stats, end_score_stats, predicate);
const auto position = std::distance(begin_score_stats, iter_position);
/* If iter_position == end_score_stats, then the player's score does
* not beat any of the existing high scores. Include a special case

View File

@ -437,7 +437,7 @@ void wall_open_door(const vmsegptridx_t seg, const sidenum_t side)
if (w->state == wall_state::closing) { //closing, so reuse door
const auto &&r = make_range(vmactdoorptr);
const auto &&re = r.end();
const auto &&i = std::ranges::find_if(r.begin(), re, find_active_door_predicate(wall_num));
const auto &&i = ranges::find_if(r.begin(), re, find_active_door_predicate(wall_num));
if (i == re) // likely in demo playback or multiplayer
{
const auto c = ActiveDoors.get_count();
@ -550,7 +550,7 @@ void start_wall_cloak(const vmsegptridx_t seg, const sidenum_t side)
{ //decloaking, so reuse door
const auto &&r = make_range(CloakingWalls.vmptr);
const auto &&re = r.end();
const auto &&i = std::ranges::find_if(r.begin(), re, find_cloaked_wall_predicate(w));
const auto &&i = ranges::find_if(r.begin(), re, find_cloaked_wall_predicate(w));
if (i == re)
{
d_debugbreak();
@ -627,7 +627,7 @@ void start_wall_decloak(const vmsegptridx_t seg, const sidenum_t side)
if (w->state == wall_state::cloaking) { //cloaking, so reuse door
const auto &&r = make_range(CloakingWalls.vmptr);
const auto &&re = r.end();
const auto &&i = std::ranges::find_if(r.begin(), re, find_cloaked_wall_predicate(w));
const auto &&i = ranges::find_if(r.begin(), re, find_cloaked_wall_predicate(w));
if (i == re)
{
d_debugbreak();
@ -800,7 +800,7 @@ void wall_close_door(wall_array &Walls, const vmsegptridx_t seg, const sidenum_t
{ //reuse door
const auto &&r = make_range(vmactdoorptr);
const auto &&re = r.end();
const auto &&i = std::ranges::find_if(r.begin(), re, find_active_door_predicate(wall_num));
const auto &&i = ranges::find_if(r.begin(), re, find_active_door_predicate(wall_num));
if (i == re)
{
d_debugbreak();
@ -1463,7 +1463,7 @@ void d_level_unique_stuck_object_state::remove_stuck_object(const vcobjidx_t obj
auto &&pr = partial_range(Stuck_objects, Num_stuck_objects);
auto &&pre = pr.end();
const auto predicate = [obj](const stuckobj &so) { return so.objnum == obj; };
const auto &&i = std::ranges::find_if(pr.begin(), pre, predicate);
const auto &&i = ranges::find_if(pr.begin(), pre, predicate);
if (i == pre)
/* Objects enter this function if they are able to become stuck,
* without regard to whether they actually are stuck. If the

View File

@ -71,7 +71,7 @@ char *PHYSFSX_fgets_t::get(const std::span<char> buf, PHYSFS_File *const fp)
return cleanup();
}
int PHYSFSX_checkMatchingExtension(const char *filename, const std::ranges::subrange<const file_extension_t *> range)
int PHYSFSX_checkMatchingExtension(const char *filename, const ranges::subrange<const file_extension_t *> range)
{
const char *ext = strrchr(filename, '.');
if (!ext)
@ -504,7 +504,7 @@ static inline PHYSFSX_uncounted_list PHYSFSX_findPredicateFiles(const char *path
// Find files at path that have an extension listed in exts
// The extension list exts must be NULL-terminated, with each ext beginning with a '.'
PHYSFSX_uncounted_list PHYSFSX_findFiles(const char *path, const std::ranges::subrange<const file_extension_t *> exts)
PHYSFSX_uncounted_list PHYSFSX_findFiles(const char *path, const ranges::subrange<const file_extension_t *> exts)
{
const auto predicate = [&](const char *i) {
return PHYSFSX_checkMatchingExtension(i, exts);
@ -514,7 +514,7 @@ PHYSFSX_uncounted_list PHYSFSX_findFiles(const char *path, const std::ranges::su
// Same function as above but takes a real directory as second argument, only adding files originating from this directory.
// This can be used to further seperate files in search path but it must be made sure realpath is properly formatted.
PHYSFSX_uncounted_list PHYSFSX_findabsoluteFiles(const char *path, const char *realpath, const std::ranges::subrange<const file_extension_t *> exts)
PHYSFSX_uncounted_list PHYSFSX_findabsoluteFiles(const char *path, const char *realpath, const ranges::subrange<const file_extension_t *> exts)
{
const auto predicate = [&](const char *i) {
return PHYSFSX_checkMatchingExtension(i, exts) && (!strcmp(PHYSFS_getRealDir(i), realpath));