Skip to content

Conversation

@JMazurkiewicz
Copy link
Contributor

Add std::bind_front<NTTP> function from P2714R1.

Previous PR (std::not_fn<NTTP>): #86133. Towards #105388.

@JMazurkiewicz JMazurkiewicz requested a review from a team as a code owner October 25, 2025 13:18
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Oct 25, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 25, 2025

@llvm/pr-subscribers-libcxx

Author: Jakub Mazurkiewicz (JMazurkiewicz)

Changes

Add std::bind_front&lt;NTTP&gt; function from P2714R1.

Previous PR (std::not_fn&lt;NTTP&gt;): #86133. Towards #105388.


Full diff: https://github.com/llvm/llvm-project/pull/165096.diff

6 Files Affected:

  • (modified) libcxx/include/__functional/bind_front.h (+34)
  • (modified) libcxx/include/functional (+2)
  • (added) libcxx/test/libcxx/utilities/function.objects/func.bind.partial/bind_front.nttp.nodiscard.verify.cpp (+19)
  • (added) libcxx/test/std/utilities/function.objects/func.bind.partial/bind_front.nttp.pass.cpp (+355)
  • (added) libcxx/test/std/utilities/function.objects/func.bind.partial/bind_front.nttp.verify.cpp (+64)
  • (modified) libcxx/test/std/utilities/function.objects/func.bind.partial/types.h (+5)
diff --git a/libcxx/include/__functional/bind_front.h b/libcxx/include/__functional/bind_front.h
index 87ef3affe80b6..1813209720cf9 100644
--- a/libcxx/include/__functional/bind_front.h
+++ b/libcxx/include/__functional/bind_front.h
@@ -17,6 +17,8 @@
 #include <__type_traits/decay.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/is_constructible.h>
+#include <__type_traits/is_member_pointer.h>
+#include <__type_traits/is_pointer.h>
 #include <__utility/forward.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -49,6 +51,38 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto bind_front(_Fn&& __f, _Args&&... __args) {
 
 #endif // _LIBCPP_STD_VER >= 20
 
+#if _LIBCPP_STD_VER >= 26
+
+template <auto _Fn>
+struct __nttp_bind_front_op {
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const
+      noexcept(noexcept(std::invoke(_Fn, std::forward<_Args>(__args)...)))
+          -> decltype(std::invoke(_Fn, std::forward<_Args>(__args)...)) {
+    return std::invoke(_Fn, std::forward<_Args>(__args)...);
+  }
+};
+
+template <auto _Fn, class... _BoundArgs>
+struct __nttp_bind_front_t : __perfect_forward<__nttp_bind_front_op<_Fn>, _BoundArgs...> {
+  using __perfect_forward<__nttp_bind_front_op<_Fn>, _BoundArgs...>::__perfect_forward;
+};
+
+template <auto _Fn, class... _Args>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto bind_front(_Args&&... __args) {
+  static_assert((is_constructible_v<decay_t<_Args>, _Args> && ...),
+                "bind_front requires all decay_t<Args> to be constructible from respective Args");
+  static_assert((is_move_constructible_v<decay_t<_Args>> && ...),
+                "bind_front requires all decay_t<Args> to be move constructible");
+  if constexpr (using _Ty = decltype(_Fn); is_pointer_v<_Ty> || is_member_pointer_v<_Ty>) {
+    static_assert(_Fn != nullptr, "f cannot be equal to nullptr");
+  }
+
+  return __nttp_bind_front_t<_Fn, decay_t<_Args>...>(std::forward<_Args>(__args)...);
+}
+
+#endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP___FUNCTIONAL_BIND_FRONT_H
diff --git a/libcxx/include/functional b/libcxx/include/functional
index 9ebcd818ec840..020754a96432c 100644
--- a/libcxx/include/functional
+++ b/libcxx/include/functional
@@ -221,6 +221,8 @@ template <auto f>
 // [func.bind.partial], function templates bind_front and bind_back
 template<class F, class... Args>
   constexpr unspecified bind_front(F&&, Args&&...); // C++20
+template<auto f, class... Args>
+  constexpr unspecified bind_front(Args&&...);      // C++26
 template<class F, class... Args>
   constexpr unspecified bind_back(F&&, Args&&...);  // C++23
 
diff --git a/libcxx/test/libcxx/utilities/function.objects/func.bind.partial/bind_front.nttp.nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/function.objects/func.bind.partial/bind_front.nttp.nodiscard.verify.cpp
new file mode 100644
index 0000000000000..3fcee5b9a2bad
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/function.objects/func.bind.partial/bind_front.nttp.nodiscard.verify.cpp
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <functional>
+
+// Test the libc++ extension that std::bind_front<NTTP> is marked as [[nodiscard]].
+
+#include <functional>
+
+void test() {
+  std::bind_front<test>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+}
diff --git a/libcxx/test/std/utilities/function.objects/func.bind.partial/bind_front.nttp.pass.cpp b/libcxx/test/std/utilities/function.objects/func.bind.partial/bind_front.nttp.pass.cpp
new file mode 100644
index 0000000000000..12c751618bea9
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/func.bind.partial/bind_front.nttp.pass.cpp
@@ -0,0 +1,355 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <functional>
+
+// template<auto f, class... Args>
+//   constexpr unspecified bind_front(Args&&...);
+
+#include <functional>
+
+#include <cassert>
+#include <concepts>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "types.h"
+
+constexpr void test_basic_bindings() {
+  { // Bind arguments, call without arguments
+    {
+      auto f = std::bind_front<MakeTuple{}>();
+      assert(f() == std::make_tuple());
+    }
+    {
+      auto f = std::bind_front<MakeTuple{}>(Elem<1>{});
+      assert(f() == std::make_tuple(Elem<1>{}));
+    }
+    {
+      auto f = std::bind_front<MakeTuple{}>(Elem<1>{}, Elem<2>{});
+      assert(f() == std::make_tuple(Elem<1>{}, Elem<2>{}));
+    }
+    {
+      auto f = std::bind_front<MakeTuple{}>(Elem<1>{}, Elem<2>{}, Elem<3>{});
+      assert(f() == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}));
+    }
+  }
+
+  { // Bind no arguments, call with arguments
+    {
+      auto f = std::bind_front<MakeTuple{}>();
+      assert(f(Elem<1>{}) == std::make_tuple(Elem<1>{}));
+    }
+    {
+      auto f = std::bind_front<MakeTuple{}>();
+      assert(f(Elem<1>{}, Elem<2>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}));
+    }
+    {
+      auto f = std::bind_front<MakeTuple{}>();
+      assert(f(Elem<1>{}, Elem<2>{}, Elem<3>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}));
+    }
+  }
+
+  { // Bind arguments, call with arguments
+    {
+      auto f = std::bind_front<MakeTuple{}>(Elem<1>{});
+      assert(f(Elem<10>{}) == std::make_tuple(Elem<1>{}, Elem<10>{}));
+    }
+    {
+      auto f = std::bind_front<MakeTuple{}>(Elem<1>{}, Elem<2>{});
+      assert(f(Elem<10>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<10>{}));
+    }
+    {
+      auto f = std::bind_front<MakeTuple{}>(Elem<1>{}, Elem<2>{}, Elem<3>{});
+      assert(f(Elem<10>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}, Elem<10>{}));
+    }
+
+    {
+      auto f = std::bind_front<MakeTuple{}>(Elem<1>{});
+      assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<1>{}, Elem<10>{}, Elem<11>{}));
+    }
+    {
+      auto f = std::bind_front<MakeTuple{}>(Elem<1>{}, Elem<2>{});
+      assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<10>{}, Elem<11>{}));
+    }
+    {
+      auto f = std::bind_front<MakeTuple{}>(Elem<1>{}, Elem<2>{}, Elem<3>{});
+      assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}, Elem<10>{}, Elem<11>{}));
+    }
+    {
+      auto f = std::bind_front<MakeTuple{}>(Elem<1>{}, Elem<2>{}, Elem<3>{});
+      assert(f(Elem<10>{}, Elem<11>{}, Elem<12>{}) ==
+             std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}, Elem<10>{}, Elem<11>{}, Elem<12>{}));
+    }
+  }
+
+  { // Basic tests with fundamental types
+    const int n = 2;
+    const int m = 1;
+    int o       = 0;
+
+    auto add       = [](int x, int y) { return x + y; };
+    auto add6      = [](int a, int b, int c, int d, int e, int f) { return a + b + c + d + e + f; };
+    auto increment = [](int& x) { return ++x; };
+
+    auto a = std::bind_front<add>(m, n);
+    assert(a() == 3);
+
+    auto b = std::bind_front<add6>(m, n, m, m, m, m);
+    assert(b() == 7);
+
+    auto c = std::bind_front<add6>(n, m);
+    assert(c(1, 1, 1, 1) == 7);
+
+    auto f = std::bind_front<add>(n);
+    assert(f(3) == 5);
+
+    auto g = std::bind_front<add>(n, 1);
+    assert(g() == 3);
+
+    auto h = std::bind_front<add6>(1, 1, 1);
+    assert(h(2, 2, 2) == 9);
+
+    auto i = std::bind_front<increment>();
+    assert(i(o) == 1);
+    assert(o == 1);
+
+    auto j = std::bind_front<increment>(std::ref(o));
+    assert(j() == 2);
+    assert(o == 2);
+  }
+}
+
+constexpr void test_edge_cases() {
+  { // Make sure we don't treat std::reference_wrapper specially.
+    auto sub = [](std::reference_wrapper<int> a, std::reference_wrapper<int> b) { return a.get() - b.get(); };
+
+    int i  = 1;
+    int j  = 2;
+    auto f = std::bind_front<sub>(std::ref(i));
+    assert(f(std::ref(j)) == -1);
+  }
+
+  { // Make sure we can call a function that's a pointer to a member function.
+    struct MemberFunction {
+      constexpr int mul(int x, int y) { return x * y; }
+    };
+
+    MemberFunction value;
+    auto fn = std::bind_front<&MemberFunction::mul>(value, 2);
+    assert(fn(3) == 6);
+  }
+
+  { // Make sure we can call a function that's a pointer to a member object.
+    struct MemberObject {
+      int obj;
+    };
+
+    MemberObject value{.obj = 3};
+    auto fn1 = std::bind_front<&MemberObject::obj>();
+    assert(fn1(value) == 3);
+    auto fn2 = std::bind_front<&MemberObject::obj>(value);
+    assert(fn2() == 3);
+  }
+}
+
+constexpr void test_passing_arguments() {
+  { // Make sure that we copy the bound arguments into the unspecified-type.
+    int n  = 2;
+    auto f = std::bind_front<[](int x, int y) { return x + y; }>(n, 1);
+    n      = 100;
+    assert(f() == 3);
+  }
+
+  { // Make sure we pass the bound arguments to the function object
+    // with the right value category.
+    {
+      auto was_copied = [](CopyMoveInfo info) { return info.copy_kind == CopyMoveInfo::copy; };
+      CopyMoveInfo info;
+      auto f = std::bind_front<was_copied>(info);
+      assert(f());
+    }
+
+    {
+      auto was_moved = [](CopyMoveInfo info) { return info.copy_kind == CopyMoveInfo::move; };
+      CopyMoveInfo info;
+      auto f = std::bind_front<was_moved>(info);
+      assert(std::move(f)());
+    }
+  }
+}
+
+constexpr void test_perfect_forwarding_call_wrapper() {
+  { // Make sure we call the correctly cv-ref qualified operator()
+    // based on the value category of the bind_front<NTTP> unspecified-type.
+    struct X {
+      constexpr int operator()() & { return 1; }
+      constexpr int operator()() const& { return 2; }
+      constexpr int operator()() && { return 3; }
+      constexpr int operator()() const&& { return 4; }
+    };
+
+    auto f  = std::bind_front<X{}>();
+    using F = decltype(f);
+    assert(static_cast<F&>(f)() == 2);
+    assert(static_cast<const F&>(f)() == 2);
+    assert(static_cast<F&&>(f)() == 2);
+    assert(static_cast<const F&&>(f)() == 2);
+  }
+
+  // Call to `bind_front<NTTP>` unspecified-type's operator() should always result in call to the const& overload of the underlying function object.
+  {
+    { // Make sure unspecified-type is still callable when we delete the & overload.
+      struct X {
+        int operator()() & = delete;
+        int operator()() const&;
+        int operator()() &&;
+        int operator()() const&&;
+      };
+
+      using F = decltype(std::bind_front<X{}>());
+      static_assert(std::invocable<F&>);
+      static_assert(std::invocable<const F&>);
+      static_assert(std::invocable<F>);
+      static_assert(std::invocable<const F>);
+    }
+
+    { // Make sure unspecified-type is not callable when we delete the const& overload.
+      struct X {
+        int operator()() &;
+        int operator()() const& = delete;
+        int operator()() &&;
+        int operator()() const&&;
+      };
+
+      using F = decltype(std::bind_front<X{}>());
+      static_assert(!std::invocable<F&>);
+      static_assert(!std::invocable<const F&>);
+      static_assert(!std::invocable<F>);
+      static_assert(!std::invocable<const F>);
+    }
+
+    { // Make sure unspecified-type is still callable when we delete the && overload.
+      struct X {
+        int operator()() &;
+        int operator()() const&;
+        int operator()() && = delete;
+        int operator()() const&&;
+      };
+
+      using F = decltype(std::bind_front<X{}>());
+      static_assert(std::invocable<F&>);
+      static_assert(std::invocable<const F&>);
+      static_assert(std::invocable<F>);
+      static_assert(std::invocable<const F>);
+    }
+
+    { // Make sure unspecified-type is still callable when we delete the const&& overload.
+      struct X {
+        int operator()() &;
+        int operator()() const&;
+        int operator()() &&;
+        int operator()() const&& = delete;
+      };
+
+      using F = decltype(std::bind_front<X{}>());
+      static_assert(std::invocable<F&>);
+      static_assert(std::invocable<const F&>);
+      static_assert(std::invocable<F>);
+      static_assert(std::invocable<const F>);
+    }
+  }
+
+  { // Test perfect forwarding
+    auto f = [](int& val) {
+      val = 5;
+      return 10;
+    };
+
+    auto bf = std::bind_front<f>();
+    int val = 0;
+    assert(bf(val) == 10);
+    assert(val == 5);
+
+    using BF = decltype(bf);
+    static_assert(std::invocable<BF, int&>);
+    static_assert(!std::invocable<BF, int>);
+  }
+}
+
+constexpr void test_return_type() {
+  { // Test constructors and assignment operators
+    struct LeftShift {
+      constexpr unsigned int operator()(unsigned int x, unsigned int y) const { return x << y; }
+    };
+
+    auto power_of_2 = std::bind_front<LeftShift{}>(1);
+    assert(power_of_2(5) == 32U);
+    assert(power_of_2(4) == 16U);
+
+    auto moved = std::move(power_of_2);
+    assert(moved(6) == 64);
+    assert(moved(7) == 128);
+
+    auto copied = power_of_2;
+    assert(copied(3) == 8);
+    assert(copied(2) == 4);
+
+    moved = std::move(copied);
+    assert(copied(1) == 2);
+    assert(copied(0) == 1);
+
+    copied = moved;
+    assert(copied(8) == 256);
+    assert(copied(9) == 512);
+  }
+
+  { // Make sure `bind_front<NTTP>` unspecified-type's operator() is SFINAE-friendly.
+    using F = decltype(std::bind_front<[](int x, int y) { return x / y; }>(1));
+    static_assert(!std::is_invocable<F>::value);
+    static_assert(std::is_invocable<F, int>::value);
+    static_assert(!std::is_invocable<F, void*>::value);
+    static_assert(!std::is_invocable<F, int, int>::value);
+  }
+
+  { // Test noexceptness
+    auto always_noexcept = std::bind_front<MaybeNoexceptFn<true>{}>();
+    static_assert(noexcept(always_noexcept()));
+
+    auto never_noexcept = std::bind_front<MaybeNoexceptFn<false>{}>();
+    static_assert(!noexcept(never_noexcept()));
+  }
+
+  { // Test calling volatile wrapper
+    using Fn = decltype(std::bind_front<std::integral_constant<int, 0>{}>());
+    static_assert(!std::invocable<volatile Fn&>);
+    static_assert(!std::invocable<const volatile Fn&>);
+    static_assert(!std::invocable<volatile Fn>);
+    static_assert(!std::invocable<const volatile Fn>);
+  }
+}
+
+constexpr bool test() {
+  test_basic_bindings();
+  test_edge_cases();
+  test_passing_arguments();
+  test_perfect_forwarding_call_wrapper();
+  test_return_type();
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert((test(), true));
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/function.objects/func.bind.partial/bind_front.nttp.verify.cpp b/libcxx/test/std/utilities/function.objects/func.bind.partial/bind_front.nttp.verify.cpp
new file mode 100644
index 0000000000000..9bdf7797aafeb
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/func.bind.partial/bind_front.nttp.verify.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <functional>
+
+// template<auto f, class... Args>
+//   constexpr unspecified bind_front(Args&&...);
+// Mandates:
+// - (is_constructible_v<BoundArgs, Args> && ...) is true, and
+// - (is_move_constructible_v<BoundArgs> && ...) is true, and
+// - If is_pointer_v<F> || is_member_pointer_v<F> is true, then f != nullptr is true.
+
+#include <functional>
+
+struct AnyArgs {
+  template <class... Args>
+  void operator()(Args&&...) {}
+};
+
+void test() {
+  { // (is_constructible_v<BoundArgs, Args> && ...) is true
+    struct Arg {
+      Arg()           = default;
+      Arg(const Arg&) = default;
+      Arg(Arg&)       = delete;
+    };
+
+    Arg arg;
+    auto _ = std::bind_front<AnyArgs{}>(arg);
+    // expected-error@*:* {{static assertion failed due to requirement 'is_constructible_v<Arg, Arg &>': bind_front requires all decay_t<Args> to be constructible from respective Args}}
+  }
+
+  { // (is_move_constructible_v<BoundArgs> && ...) is true
+    struct Arg {
+      Arg()           = default;
+      Arg(Arg&&)      = delete;
+      Arg(const Arg&) = default;
+    };
+
+    Arg arg;
+    auto _ = std::bind_front<AnyArgs{}>(arg);
+    // expected-error@*:* {{static assertion failed due to requirement 'is_move_constructible_v<Arg>': bind_front requires all decay_t<Args> to be move constructible}}
+  }
+
+  { // If is_pointer_v<F> || is_member_pointer_v<F> is true, then f != nullptr is true
+    struct X {};
+
+    auto _ = std::bind_front<static_cast<void (*)()>(nullptr)>();
+    // expected-error@*:* {{static assertion failed due to requirement 'nullptr != nullptr': f cannot be equal to nullptr}}
+
+    auto _ = std::bind_front<static_cast<int X::*>(nullptr)>();
+    // expected-error@*:* {{static assertion failed due to requirement 'nullptr != nullptr': f cannot be equal to nullptr}}
+
+    auto _ = std::bind_front<static_cast<void (X::*)()>(nullptr)>();
+    // expected-error@*:* {{static assertion failed due to requirement 'nullptr != nullptr': f cannot be equal to nullptr}}
+  }
+}
diff --git a/libcxx/test/std/utilities/function.objects/func.bind.partial/types.h b/libcxx/test/std/utilities/function.objects/func.bind.partial/types.h
index 76ed4d478baac..98277e6231895 100644
--- a/libcxx/test/std/utilities/function.objects/func.bind.partial/types.h
+++ b/libcxx/test/std/utilities/function.objects/func.bind.partial/types.h
@@ -40,4 +40,9 @@ T do_nothing(T t) {
   return t;
 }
 
+template <bool IsNoexcept>
+struct MaybeNoexceptFn {
+  bool operator()() const noexcept(IsNoexcept); // not defined
+};
+
 #endif // TEST_STD_UTILITIES_FUNCTION_OBJECTS_FUNC_BIND_PARTIAL_TYPES_H


template <auto _Fn, class... _BoundArgs>
struct __nttp_bind_front_t : __perfect_forward<__nttp_bind_front_op<_Fn>, _BoundArgs...> {
using __perfect_forward<__nttp_bind_front_op<_Fn>, _BoundArgs...>::__perfect_forward;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to use explicit this parameters.

static_assert(_Fn != nullptr, "f cannot be equal to nullptr");
}

return __nttp_bind_front_t<_Fn, decay_t<_Args>...>(std::forward<_Args>(__args)...);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When sizeof...(_Args) == 0, it seems better to return a functor with static operator().

@@ -0,0 +1,64 @@
//===----------------------------------------------------------------------===//
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No change requested for this file. The test failure said

2025-10-25T13:32:25.4922439Z # .---command stderr------------
2025-10-25T13:32:25.4923105Z # | error: 'expected-error' diagnostics seen but not expected: 
2025-10-25T13:32:25.4924660Z # |   File /home/gha/actions-runner/_work/llvm-project/llvm-project/build/generic-cxx26/libcxx/test-suite-install/include/c++/v1/__functional/bind_front.h Line 73: call to deleted constructor of 'Arg'
2025-10-25T13:32:25.4926047Z # | 1 error generated.
2025-10-25T13:32:25.4926371Z # `-----------------------------

But I think we can get rid of deleted overloads if we use explicit this parameters.

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants