Skip to content

[libc++] <ranges>: ranges::to use range-based for loops in append branches #119133

@hewillk

Description

@hewillk

for (auto&& __ref : __range) {
using _Ref = decltype(__ref);
if constexpr (requires { __result.emplace_back(std::declval<_Ref>()); }) {
__result.emplace_back(std::forward<_Ref>(__ref));
} else if constexpr (requires { __result.push_back(std::declval<_Ref>()); }) {
__result.push_back(std::forward<_Ref>(__ref));
} else if constexpr (requires { __result.emplace(__result.end(), std::declval<_Ref>()); }) {
__result.emplace(__result.end(), std::forward<_Ref>(__ref));
} else {
static_assert(requires { __result.insert(__result.end(), std::declval<_Ref>()); });
__result.insert(__result.end(), std::forward<_Ref>(__ref));
}
}

Range-based for loop is not guaranteed to be well-formed for input_range as it does not extract iterator-pair through ranges::begin/ranges::end:

https://godbolt.org/z/Kc3dsvnfW

#include <ranges>

struct Vector {
  void push_back(int);
};

struct OnlyADLRange {
  void begin() = delete;
  void end() = delete;
  friend int* begin(OnlyADLRange&);
  friend int* end(OnlyADLRange&);
};

int main() {
  std::ranges::contiguous_range auto r = OnlyADLRange{};
  auto v = r | std::ranges::to<Vector>(); // only well-formed in libstdc++
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.rangesIssues related to `<ranges>`

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions