[libcxx-commits] [libcxx] [libc++][ranges] LWG4016: container-insertable checks do not match what container-inserter does (PR #113103)

Xiaoyang Liu via libcxx-commits libcxx-commits at lists.llvm.org
Sun Oct 20 19:01:12 PDT 2024


================
@@ -54,19 +52,26 @@ constexpr bool __reservable_container =
     };
 
 template <class _Container, class _Ref>
-constexpr bool __container_insertable = requires(_Container& __c, _Ref&& __ref) {
+constexpr bool __container_appendable = requires(_Container& __c, _Ref&& __ref) {
   requires(
+      requires { __c.emplace_back(std::forward<_Ref>(__ref)); } ||
       requires { __c.push_back(std::forward<_Ref>(__ref)); } ||
+      requires { __c.emplace(__c.end(), std::forward<_Ref>(__ref)); } ||
       requires { __c.insert(__c.end(), std::forward<_Ref>(__ref)); });
 };
 
-template <class _Ref, class _Container>
-_LIBCPP_HIDE_FROM_ABI constexpr auto __container_inserter(_Container& __c) {
-  if constexpr (requires { __c.push_back(std::declval<_Ref>()); }) {
-    return std::back_inserter(__c);
-  } else {
-    return std::inserter(__c, __c.end());
-  }
+template <class _Container>
+_LIBCPP_HIDE_FROM_ABI constexpr auto __container_append(_Container& __c) {
+  return [&__c]<class _Ref>(_Ref&& __ref) {
+    if constexpr (requires { __c.emplace_back(declval<_Ref>()); })
+      __c.emplace_back(std::forward<_Ref>(__ref));
+    else if constexpr (requires { __c.push_back(declval<_Ref>()); })
+      __c.push_back(std::forward<_Ref>(__ref));
+    else if constexpr (requires { __c.emplace(__c.end(), declval<_Ref>()); })
+      __c.emplace(__c.end(), std::forward<_Ref>(__ref));
+    else if constexpr (requires { __c.insert(__c.end(), declval<_Ref>()); })
----------------
xiaoyang-sde wrote:

A full `if constexpr` condition is required instead of just using `else`, as Clang has not yet implemented [P0588R1](https://wg21.link/P0588R1). Without this proposal, when the function template `__container_append` is instantiated, Clang partially instantiates the body of the returned generic lambda. Using `else` in this scenario causes Clang to attempt evaluating `__c.insert(__c.end(), std::forward<_Ref>(__ref));` even when this statement should be discarded, which can result in an error if `__c` lacks a valid `insert` method.

https://github.com/llvm/llvm-project/pull/113103


More information about the libcxx-commits mailing list