Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
hewillk opened this issue Dec 8, 2024 · 4 comments · May be fixed by #119161
Open

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

hewillk opened this issue Dec 8, 2024 · 4 comments · May be fixed by #119161
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. ranges Issues related to `<ranges>`

Comments

@hewillk
Copy link
Contributor

hewillk commented Dec 8, 2024

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++
}
@hewillk hewillk changed the title <ranges>: ranges::to use range-based for loops in append branches [libc++] <ranges>: ranges::to use range-based for loops in append branches Dec 8, 2024
@frederick-vs-ja frederick-vs-ja added libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. ranges Issues related to `<ranges>` and removed new issue labels Dec 9, 2024
@hewillk
Copy link
Contributor Author

hewillk commented Dec 9, 2024

range_formatter have similar issues:

for (auto&& __e : __range) {
if (__use_separator)
__ctx.advance_to(ranges::copy(__separator_, __ctx.out()).out);
else
__use_separator = true;

@hewillk
Copy link
Contributor Author

hewillk commented Dec 9, 2024

It looks like libc++ extensively uses range-for loops to iterate over ranges when implementing P1206, so this should be something that can be modified uniformly (if worth it).

@frederick-vs-ja
Copy link
Contributor

I think I can fix these issues (if wanted). But they mean that we can't traverse a range using range-for in generic code, which sounds weird.

@philnik777
Copy link
Contributor

Yeah, I think there should be an LWG or CWG issue about this. Not being able to iterate a range with a range-based for loop sounds a lot like a design flaw to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. ranges Issues related to `<ranges>`
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants