Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
/* Constant Value
__cpp_lib_array_constexpr 201603L [C++17]
201811L [C++2a]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_nonmember_container_access 201411L [C++17]
__cpp_lib_to_array 201907L [C++2a]
*/
Expand All @@ -30,10 +29,6 @@
# error "__cpp_lib_array_constexpr should not be defined before c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_nonmember_container_access
# error "__cpp_lib_nonmember_container_access should not be defined before c++17"
# endif
Expand All @@ -48,10 +43,6 @@
# error "__cpp_lib_array_constexpr should not be defined before c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_nonmember_container_access
# error "__cpp_lib_nonmember_container_access should not be defined before c++17"
# endif
Expand All @@ -69,10 +60,6 @@
# error "__cpp_lib_array_constexpr should have the value 201603L in c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifndef __cpp_lib_nonmember_container_access
# error "__cpp_lib_nonmember_container_access should be defined in c++17"
# endif
Expand All @@ -93,19 +80,6 @@
# error "__cpp_lib_array_constexpr should have the value 201811L in c++2a"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_misc != 201811L
# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!"
# endif
# endif

# ifndef __cpp_lib_nonmember_container_access
# error "__cpp_lib_nonmember_container_access should be defined in c++2a"
# endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
/* Constant Value
__cpp_lib_bind_front 201811L [C++2a]
__cpp_lib_boyer_moore_searcher 201603L [C++17]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_constexpr_functional 201907L [C++2a]
__cpp_lib_invoke 201411L [C++17]
__cpp_lib_not_fn 201603L [C++17]
__cpp_lib_ranges 201811L [C++2a]
Expand All @@ -38,8 +38,8 @@
# error "__cpp_lib_boyer_moore_searcher should not be defined before c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# ifdef __cpp_lib_constexpr_functional
# error "__cpp_lib_constexpr_functional should not be defined before c++2a"
# endif

# ifdef __cpp_lib_invoke
Expand Down Expand Up @@ -72,8 +72,8 @@
# error "__cpp_lib_boyer_moore_searcher should not be defined before c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# ifdef __cpp_lib_constexpr_functional
# error "__cpp_lib_constexpr_functional should not be defined before c++2a"
# endif

# ifdef __cpp_lib_invoke
Expand Down Expand Up @@ -121,8 +121,8 @@
# endif
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# ifdef __cpp_lib_constexpr_functional
# error "__cpp_lib_constexpr_functional should not be defined before c++2a"
# endif

# ifndef __cpp_lib_invoke
Expand Down Expand Up @@ -185,17 +185,11 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_misc != 201811L
# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_constexpr_functional
# error "__cpp_lib_constexpr_functional should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_functional != 201907L
# error "__cpp_lib_constexpr_functional should have the value 201907L in c++2a"
# endif

# ifndef __cpp_lib_invoke
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
/* Constant Value
__cpp_lib_array_constexpr 201603L [C++17]
201811L [C++2a]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_make_reverse_iterator 201402L [C++14]
__cpp_lib_nonmember_container_access 201411L [C++17]
__cpp_lib_null_iterators 201304L [C++14]
Expand All @@ -32,10 +31,6 @@
# error "__cpp_lib_array_constexpr should not be defined before c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_make_reverse_iterator
# error "__cpp_lib_make_reverse_iterator should not be defined before c++14"
# endif
Expand All @@ -58,10 +53,6 @@
# error "__cpp_lib_array_constexpr should not be defined before c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifndef __cpp_lib_make_reverse_iterator
# error "__cpp_lib_make_reverse_iterator should be defined in c++14"
# endif
Expand Down Expand Up @@ -93,10 +84,6 @@
# error "__cpp_lib_array_constexpr should have the value 201603L in c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifndef __cpp_lib_make_reverse_iterator
# error "__cpp_lib_make_reverse_iterator should be defined in c++17"
# endif
Expand Down Expand Up @@ -131,19 +118,6 @@
# error "__cpp_lib_array_constexpr should have the value 201811L in c++2a"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_misc != 201811L
# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!"
# endif
# endif

# ifndef __cpp_lib_make_reverse_iterator
# error "__cpp_lib_make_reverse_iterator should be defined in c++2a"
# endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@

// Test the feature test macros defined by <string_view>

/* Constant Value
__cpp_lib_char8_t 201811L [C++2a]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_string_view 201606L [C++17]
/* Constant Value
__cpp_lib_char8_t 201811L [C++2a]
__cpp_lib_string_view 201606L [C++17]
*/

#include <string_view>
Expand All @@ -28,10 +27,6 @@
# error "__cpp_lib_char8_t should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_string_view
# error "__cpp_lib_string_view should not be defined before c++17"
# endif
Expand All @@ -42,10 +37,6 @@
# error "__cpp_lib_char8_t should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_string_view
# error "__cpp_lib_string_view should not be defined before c++17"
# endif
Expand All @@ -56,10 +47,6 @@
# error "__cpp_lib_char8_t should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifndef __cpp_lib_string_view
# error "__cpp_lib_string_view should be defined in c++17"
# endif
Expand All @@ -82,19 +69,6 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_misc != 201811L
# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!"
# endif
# endif

# ifndef __cpp_lib_string_view
# error "__cpp_lib_string_view should be defined in c++2a"
# endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

/* Constant Value
__cpp_lib_apply 201603L [C++17]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_make_from_tuple 201606L [C++17]
__cpp_lib_tuple_element_t 201402L [C++14]
__cpp_lib_tuples_by_type 201304L [C++14]
Expand All @@ -30,10 +29,6 @@
# error "__cpp_lib_apply should not be defined before c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_make_from_tuple
# error "__cpp_lib_make_from_tuple should not be defined before c++17"
# endif
Expand All @@ -52,10 +47,6 @@
# error "__cpp_lib_apply should not be defined before c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_make_from_tuple
# error "__cpp_lib_make_from_tuple should not be defined before c++17"
# endif
Expand Down Expand Up @@ -83,10 +74,6 @@
# error "__cpp_lib_apply should have the value 201603L in c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifndef __cpp_lib_make_from_tuple
# error "__cpp_lib_make_from_tuple should be defined in c++17"
# endif
Expand Down Expand Up @@ -117,19 +104,6 @@
# error "__cpp_lib_apply should have the value 201603L in c++2a"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_misc != 201811L
# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!"
# endif
# endif

# ifndef __cpp_lib_make_from_tuple
# error "__cpp_lib_make_from_tuple should be defined in c++2a"
# endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

/* Constant Value
__cpp_lib_as_const 201510L [C++17]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_constexpr_utility 201811L [C++2a]
__cpp_lib_exchange_function 201304L [C++14]
__cpp_lib_integer_sequence 201304L [C++14]
Expand All @@ -32,10 +31,6 @@
# error "__cpp_lib_as_const should not be defined before c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should not be defined before c++2a"
# endif
Expand All @@ -62,10 +57,6 @@
# error "__cpp_lib_as_const should not be defined before c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should not be defined before c++2a"
# endif
Expand Down Expand Up @@ -104,10 +95,6 @@
# error "__cpp_lib_as_const should have the value 201510L in c++17"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should not be defined before c++2a"
# endif
Expand Down Expand Up @@ -155,19 +142,6 @@
# error "__cpp_lib_as_const should have the value 201510L in c++2a"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_misc != 201811L
# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!"
# endif
# endif

# ifndef __cpp_lib_constexpr_utility
# error "__cpp_lib_constexpr_utility should be defined in c++2a"
# endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
__cpp_lib_complex_udls 201309L [C++14]
__cpp_lib_concepts 201806L [C++2a]
__cpp_lib_constexpr_dynamic_alloc 201907L [C++2a]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_constexpr_functional 201907L [C++2a]
__cpp_lib_constexpr_numeric 201911L [C++2a]
__cpp_lib_constexpr_swap_algorithms 201806L [C++2a]
__cpp_lib_constexpr_utility 201811L [C++2a]
Expand Down Expand Up @@ -224,8 +224,8 @@
# error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# ifdef __cpp_lib_constexpr_functional
# error "__cpp_lib_constexpr_functional should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_numeric
Expand Down Expand Up @@ -620,8 +620,8 @@
# error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# ifdef __cpp_lib_constexpr_functional
# error "__cpp_lib_constexpr_functional should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_numeric
Expand Down Expand Up @@ -1130,8 +1130,8 @@
# error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined before c++2a"
# ifdef __cpp_lib_constexpr_functional
# error "__cpp_lib_constexpr_functional should not be defined before c++2a"
# endif

# ifdef __cpp_lib_constexpr_numeric
Expand Down Expand Up @@ -1904,17 +1904,11 @@
# error "__cpp_lib_constexpr_dynamic_alloc should have the value 201907L in c++2a"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_misc != 201811L
# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_constexpr_misc
# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_constexpr_functional
# error "__cpp_lib_constexpr_functional should be defined in c++2a"
# endif
# if __cpp_lib_constexpr_functional != 201907L
# error "__cpp_lib_constexpr_functional should have the value 201907L in c++2a"
# endif

# ifndef __cpp_lib_constexpr_numeric
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17

// <functional>

// template<class F, class... Args>
// constexpr // constexpr in C++20
// invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
// noexcept(is_nothrow_invocable_v<_Fn, _Args...>);

/// C++14 [func.def] 20.9.0
/// (1) The following definitions apply to this Clause:
/// (2) A call signature is the name of a return type followed by a parenthesized
/// comma-separated list of zero or more argument types.
/// (3) A callable type is a function object type (20.9) or a pointer to member.
/// (4) A callable object is an object of a callable type.
/// (5) A call wrapper type is a type that holds a callable object and supports
/// a call operation that forwards to that object.
/// (6) A call wrapper is an object of a call wrapper type.
/// (7) A target object is the callable object held by a call wrapper.

/// C++14 [func.require] 20.9.1
///
/// Define INVOKE (f, t1, t2, ..., tN) as follows:
/// (1.1) - (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of
/// type T or a reference to an object of type T or a reference to an object of a type derived from T;
/// (1.2) - ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of
/// the types described in the previous item;
/// (1.3) - t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a
/// reference to an object of type T or a reference to an object of a type derived from T;
/// (1.4) - (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types
/// described in the previous item;
/// (1.5) - f(t1, t2, ..., tN) in all other cases.

#include <functional>
#include <type_traits>
#include <utility> // for std::move
#include <cassert>

#include "test_macros.h"

struct NonCopyable {
constexpr NonCopyable() {}
private:
NonCopyable(NonCopyable const&) = delete;
NonCopyable& operator=(NonCopyable const&) = delete;
};

struct TestClass {
constexpr explicit TestClass(int x) : data(x) {}

constexpr int& operator()(NonCopyable&&) & { return data; }
constexpr int const& operator()(NonCopyable&&) const & { return data; }

constexpr int&& operator()(NonCopyable&&) && { return std::move(data); }
constexpr int const&& operator()(NonCopyable&&) const && { return std::move(data); }

int data;
private:
TestClass(TestClass const&) = delete;
TestClass& operator=(TestClass const&) = delete;
};

struct DerivedFromTestClass : public TestClass {
constexpr explicit DerivedFromTestClass(int x) : TestClass(x) {}
};

static constexpr int data = 42;
constexpr const int& foo(NonCopyable&&) {
return data;
}

template <class Signature, class Expect, class Functor>
constexpr void test_b12(Functor&& f) {
// Create the callable object.
typedef Signature TestClass::*ClassFunc;
ClassFunc func_ptr = &TestClass::operator();

// Create the dummy arg.
NonCopyable arg;

// Check that the deduced return type of invoke is what is expected.
typedef decltype(
std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg))
) DeducedReturnType;
static_assert((std::is_same<DeducedReturnType, Expect>::value), "");

// Check that result_of_t matches Expect.
typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type
ResultOfReturnType;
static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");

// Run invoke and check the return value.
DeducedReturnType ret =
std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg));
assert(ret == 42);
}

template <class Expect, class Functor>
constexpr void test_b34(Functor&& f) {
// Create the callable object.
typedef int TestClass::*ClassFunc;
ClassFunc func_ptr = &TestClass::data;

// Check that the deduced return type of invoke is what is expected.
typedef decltype(
std::invoke(func_ptr, std::forward<Functor>(f))
) DeducedReturnType;
static_assert((std::is_same<DeducedReturnType, Expect>::value), "");

// Check that result_of_t matches Expect.
typedef typename std::result_of<ClassFunc&&(Functor&&)>::type
ResultOfReturnType;
static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");

// Run invoke and check the return value.
DeducedReturnType ret =
std::invoke(func_ptr, std::forward<Functor>(f));
assert(ret == 42);
}

template <class Expect, class Functor>
constexpr void test_b5(Functor&& f) {
NonCopyable arg;

// Check that the deduced return type of invoke is what is expected.
typedef decltype(
std::invoke(std::forward<Functor>(f), std::move(arg))
) DeducedReturnType;
static_assert((std::is_same<DeducedReturnType, Expect>::value), "");

// Check that result_of_t matches Expect.
typedef typename std::result_of<Functor&&(NonCopyable&&)>::type
ResultOfReturnType;
static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");

// Run invoke and check the return value.
DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg));
assert(ret == 42);
}

constexpr bool bullet_one_two_tests() {
{
TestClass cl(42);
test_b12<int&(NonCopyable&&) &, int&>(cl);
test_b12<int const&(NonCopyable&&) const &, int const&>(cl);

test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
}
{
DerivedFromTestClass cl(42);
test_b12<int&(NonCopyable&&) &, int&>(cl);
test_b12<int const&(NonCopyable&&) const &, int const&>(cl);

test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
}
{
TestClass cl_obj(42);
std::reference_wrapper<TestClass> cl(cl_obj);
test_b12<int&(NonCopyable&&) &, int&>(cl);
test_b12<int const&(NonCopyable&&) const &, int const&>(cl);

test_b12<int&(NonCopyable&&) &, int&>(std::move(cl));
test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl));
}
{
DerivedFromTestClass cl_obj(42);
std::reference_wrapper<DerivedFromTestClass> cl(cl_obj);
test_b12<int&(NonCopyable&&) &, int&>(cl);
test_b12<int const&(NonCopyable&&) const &, int const&>(cl);

test_b12<int&(NonCopyable&&) &, int&>(std::move(cl));
test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl));
}
{
TestClass cl_obj(42);
TestClass *cl = &cl_obj;
test_b12<int&(NonCopyable&&) &, int&>(cl);
test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
}
{
DerivedFromTestClass cl_obj(42);
DerivedFromTestClass *cl = &cl_obj;
test_b12<int&(NonCopyable&&) &, int&>(cl);
test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
}
return true;
}

constexpr bool bullet_three_four_tests() {
{
typedef TestClass Fn;
Fn cl(42);
test_b34<int&>(cl);
test_b34<int const&>(static_cast<Fn const&>(cl));

test_b34<int&&>(static_cast<Fn &&>(cl));
test_b34<int const&&>(static_cast<Fn const&&>(cl));
}
{
typedef DerivedFromTestClass Fn;
Fn cl(42);
test_b34<int&>(cl);
test_b34<int const&>(static_cast<Fn const&>(cl));

test_b34<int&&>(static_cast<Fn &&>(cl));
test_b34<int const&&>(static_cast<Fn const&&>(cl));
}
{
typedef TestClass Fn;
Fn cl(42);
test_b34<int&>(std::reference_wrapper<Fn>(cl));
test_b34<int const&>(std::reference_wrapper<Fn const>(cl));
}
{
typedef DerivedFromTestClass Fn;
Fn cl(42);
test_b34<int&>(std::reference_wrapper<Fn>(cl));
test_b34<int const&>(std::reference_wrapper<Fn const>(cl));
}
{
typedef TestClass Fn;
Fn cl_obj(42);
Fn* cl = &cl_obj;
test_b34<int&>(cl);
test_b34<int const&>(static_cast<Fn const*>(cl));
}
{
typedef DerivedFromTestClass Fn;
Fn cl_obj(42);
Fn* cl = &cl_obj;
test_b34<int&>(cl);
test_b34<int const&>(static_cast<Fn const*>(cl));
}
return true;
}

constexpr bool bullet_five_tests() {
using FooType = const int&(NonCopyable&&);
{
FooType& fn = foo;
test_b5<const int &>(fn);
}
{
FooType* fn = foo;
test_b5<const int &>(fn);
}
{
typedef TestClass Fn;
Fn cl(42);
test_b5<int&>(cl);
test_b5<int const&>(static_cast<Fn const&>(cl));

test_b5<int&&>(static_cast<Fn &&>(cl));
test_b5<int const&&>(static_cast<Fn const&&>(cl));
}
return true;
}

int main(int, char**) {
bullet_one_two_tests();
bullet_three_four_tests();
bullet_five_tests();

static_assert(bullet_one_two_tests());
static_assert(bullet_three_four_tests());
static_assert(bullet_five_tests());

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct A
};

template <class F>
void
TEST_CONSTEXPR_CXX20 bool
test(F f)
{
{
Expand All @@ -36,11 +36,16 @@ test(F f)
const F& cf = f;
assert(cf(ap) == f(ap));
}
return true;
}

int main(int, char**)
{
test(std::mem_fn(&A::data_));

return 0;
#if TEST_STD_VER >= 20
static_assert(test(std::mem_fn(&A::data_)));
#endif

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@

struct A
{
char test0() {return 'a';}
char test1(int) {return 'b';}
char test2(int, double) {return 'c';}
TEST_CONSTEXPR_CXX14 char test0() {return 'a';}
TEST_CONSTEXPR_CXX14 char test1(int) {return 'b';}
TEST_CONSTEXPR_CXX14 char test2(int, double) {return 'c';}
};

template <class F>
void
TEST_CONSTEXPR_CXX20 bool
test0(F f)
{
{
Expand All @@ -35,10 +35,11 @@ test0(F f)
const F& cf = f;
assert(cf(ap) == 'a');
}
return true;
}

template <class F>
void
TEST_CONSTEXPR_CXX20 bool
test1(F f)
{
{
Expand All @@ -49,10 +50,11 @@ test1(F f)
const F& cf = f;
assert(cf(ap, 2) == 'b');
}
return true;
}

template <class F>
void
TEST_CONSTEXPR_CXX20 bool
test2(F f)
{
{
Expand All @@ -63,6 +65,7 @@ test2(F f)
const F& cf = f;
assert(cf(ap, 2, 3.5) == 'c');
}
return true;
}

int main(int, char**)
Expand All @@ -74,5 +77,11 @@ int main(int, char**)
static_assert((noexcept(std::mem_fn(&A::test0))), ""); // LWG#2489
#endif

return 0;
#if TEST_STD_VER >= 20
static_assert(test0(std::mem_fn(&A::test0)));
static_assert(test1(std::mem_fn(&A::test1)));
static_assert(test2(std::mem_fn(&A::test2)));
#endif

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@

struct A
{
char test0() const {return 'a';}
char test1(int) const {return 'b';}
char test2(int, double) const {return 'c';}
TEST_CONSTEXPR char test0() const {return 'a';}
TEST_CONSTEXPR char test1(int) const {return 'b';}
TEST_CONSTEXPR char test2(int, double) const {return 'c';}
};

template <class F>
void
TEST_CONSTEXPR_CXX20 bool
test0(F f)
{
{
Expand All @@ -37,10 +37,11 @@ test0(F f)
const F& cf = f;
assert(cf(ap) == 'a');
}
return true;
}

template <class F>
void
TEST_CONSTEXPR_CXX20 bool
test1(F f)
{
{
Expand All @@ -53,10 +54,11 @@ test1(F f)
const F& cf = f;
assert(cf(ap, 2) == 'b');
}
return true;
}

template <class F>
void
TEST_CONSTEXPR_CXX20 bool
test2(F f)
{
{
Expand All @@ -69,6 +71,7 @@ test2(F f)
const F& cf = f;
assert(cf(ap, 2, 3.5) == 'c');
}
return true;
}

int main(int, char**)
Expand All @@ -77,5 +80,11 @@ int main(int, char**)
test1(std::mem_fn(&A::test1));
test2(std::mem_fn(&A::test2));

return 0;
#if TEST_STD_VER >= 20
static_assert(test0(std::mem_fn(&A::test0)));
static_assert(test1(std::mem_fn(&A::test1)));
static_assert(test2(std::mem_fn(&A::test2)));
#endif

return 0;
}
248 changes: 136 additions & 112 deletions libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,15 @@
#include "test_iterators.h"

template <typename Iter1, typename Iter2>
TEST_CONSTEXPR_CXX20
void do_search(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, Iter1 result) {
std::default_searcher<Iter2> s{b2, e2};
assert(result == std::search(b1, e1, s));
}

template <class Iter1, class Iter2>
void
test()
TEST_CONSTEXPR_CXX20
bool test()
{
int ia[] = {0, 1, 2, 3, 4, 5};
const unsigned sa = sizeof(ia)/sizeof(ia[0]);
Expand Down Expand Up @@ -81,6 +82,8 @@ test()
int ik[] = {0, 0, 0, 0, 1, 1, 1, 1, 0, 0};
const unsigned sk = sizeof(ik)/sizeof(ik[0]);
do_search(Iter1(ij), Iter1(ij+sj), Iter2(ik), Iter2(ik+sk), Iter1(ij+6));

return true;
}

int main(int, char**) {
Expand All @@ -94,5 +97,17 @@ int main(int, char**) {
test<random_access_iterator<const int*>, bidirectional_iterator<const int*> >();
test<random_access_iterator<const int*>, random_access_iterator<const int*> >();

return 0;
#if TEST_STD_VER >= 20
static_assert(test<forward_iterator<const int*>, forward_iterator<const int*>>());
static_assert(test<forward_iterator<const int*>, bidirectional_iterator<const int*>>());
static_assert(test<forward_iterator<const int*>, random_access_iterator<const int*>>());
static_assert(test<bidirectional_iterator<const int*>, forward_iterator<const int*>>());
static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>>());
static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<const int*>>());
static_assert(test<random_access_iterator<const int*>, forward_iterator<const int*>>());
static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<const int*>>());
static_assert(test<random_access_iterator<const int*>, random_access_iterator<const int*>>());
#endif

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,54 +40,59 @@

struct count_equal
{
static unsigned count;
unsigned *count;

template <class T>
bool operator()(const T& x, const T& y) const
{++count; return x == y;}
TEST_CONSTEXPR_CXX14 bool operator()(const T& x, const T& y) const
{++*count; return x == y;}
};

unsigned count_equal::count = 0;

template <typename Iter1, typename Iter2>
void do_search(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, Iter1 result, unsigned max_count) {
std::default_searcher<Iter2, count_equal> s{b2, e2};
count_equal::count = 0;
TEST_CONSTEXPR_CXX20
void do_search(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, Iter1 result) {
unsigned count = 0;
std::default_searcher<Iter2, count_equal> s{b2, e2, count_equal{&count}};
assert(result == std::search(b1, e1, s));
assert(count_equal::count <= max_count);
auto d1 = std::distance(b1, e1);
auto d2 = std::distance(b2, e2);
assert((count >= 1) || (d2 == 0) || (d1 < d2));
assert((d1 < d2) || count <= d1 * (d1 - d2 + 1));
}

template <class Iter1, class Iter2>
void
test()
TEST_CONSTEXPR_CXX20
bool test()
{
int ia[] = {0, 1, 2, 3, 4, 5};
const unsigned sa = sizeof(ia)/sizeof(ia[0]);
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia), Iter1(ia), 0);
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia+1), Iter1(ia), sa);
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+1), Iter2(ia+2), Iter1(ia+1), sa);
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+2), Iter1(ia), 0);
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+3), Iter1(ia+2), sa);
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+3), Iter1(ia+2), sa);
do_search(Iter1(ia), Iter1(ia), Iter2(ia+2), Iter2(ia+3), Iter1(ia), 0);
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+sa-1), Iter2(ia+sa), Iter1(ia+sa-1), sa);
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+sa-3), Iter2(ia+sa), Iter1(ia+sa-3), 3*sa);
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia+sa), Iter1(ia), sa*sa);
do_search(Iter1(ia), Iter1(ia+sa-1), Iter2(ia), Iter2(ia+sa), Iter1(ia+sa-1), (sa-1)*sa);
do_search(Iter1(ia), Iter1(ia+1), Iter2(ia), Iter2(ia+sa), Iter1(ia+1), sa);
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia), Iter1(ia));
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia+1), Iter1(ia));
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+1), Iter2(ia+2), Iter1(ia+1));
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+2), Iter1(ia));
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+3), Iter1(ia+2));
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+3), Iter1(ia+2));
do_search(Iter1(ia), Iter1(ia), Iter2(ia+2), Iter2(ia+3), Iter1(ia));
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+sa-1), Iter2(ia+sa), Iter1(ia+sa-1));
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+sa-3), Iter2(ia+sa), Iter1(ia+sa-3));
do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia+sa), Iter1(ia));
do_search(Iter1(ia), Iter1(ia+sa-1), Iter2(ia), Iter2(ia+sa), Iter1(ia+sa-1));
do_search(Iter1(ia), Iter1(ia+1), Iter2(ia), Iter2(ia+sa), Iter1(ia+1));
int ib[] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4};
const unsigned sb = sizeof(ib)/sizeof(ib[0]);
int ic[] = {1};
do_search(Iter1(ib), Iter1(ib+sb), Iter2(ic), Iter2(ic+1), Iter1(ib+1), sb);
do_search(Iter1(ib), Iter1(ib+sb), Iter2(ic), Iter2(ic+1), Iter1(ib+1));
int id[] = {1, 2};
do_search(Iter1(ib), Iter1(ib+sb), Iter2(id), Iter2(id+2), Iter1(ib+1), sb*2);
do_search(Iter1(ib), Iter1(ib+sb), Iter2(id), Iter2(id+2), Iter1(ib+1));
int ie[] = {1, 2, 3};
do_search(Iter1(ib), Iter1(ib+sb), Iter2(ie), Iter2(ie+3), Iter1(ib+4), sb*3);
do_search(Iter1(ib), Iter1(ib+sb), Iter2(ie), Iter2(ie+3), Iter1(ib+4));
int ig[] = {1, 2, 3, 4};
do_search(Iter1(ib), Iter1(ib+sb), Iter2(ig), Iter2(ig+4), Iter1(ib+8), sb*4);
do_search(Iter1(ib), Iter1(ib+sb), Iter2(ig), Iter2(ig+4), Iter1(ib+8));
int ih[] = {0, 1, 1, 1, 1, 2, 3, 0, 1, 2, 3, 4};
const unsigned sh = sizeof(ih)/sizeof(ih[0]);
int ii[] = {1, 1, 2};
do_search(Iter1(ih), Iter1(ih+sh), Iter2(ii), Iter2(ii+3), Iter1(ih+3), sh*3);
do_search(Iter1(ih), Iter1(ih+sh), Iter2(ii), Iter2(ii+3), Iter1(ih+3));

return true;
}

int main(int, char**) {
Expand All @@ -101,5 +106,17 @@ int main(int, char**) {
test<random_access_iterator<const int*>, bidirectional_iterator<const int*> >();
test<random_access_iterator<const int*>, random_access_iterator<const int*> >();

return 0;
#if TEST_STD_VER >= 20
static_assert(test<forward_iterator<const int*>, forward_iterator<const int*>>());
static_assert(test<forward_iterator<const int*>, bidirectional_iterator<const int*>>());
static_assert(test<forward_iterator<const int*>, random_access_iterator<const int*>>());
static_assert(test<bidirectional_iterator<const int*>, forward_iterator<const int*>>());
static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>>());
static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<const int*>>());
static_assert(test<random_access_iterator<const int*>, forward_iterator<const int*>>());
static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<const int*>>());
static_assert(test<random_access_iterator<const int*>, random_access_iterator<const int*>>());
#endif

return 0;
}
7 changes: 3 additions & 4 deletions libcxx/utils/generate_feature_test_macro_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,10 +369,9 @@ def add_version_header(tc):
"headers": ["algorithm"],
"unimplemented": True,
}, {
"name": "__cpp_lib_constexpr_misc",
"values": { "c++2a": int(201811) },
"headers": ["array", "functional", "iterator", "string_view", "tuple", "utility"],
"unimplemented": True,
"name": "__cpp_lib_constexpr_functional",
"values": { "c++2a": int(201907) },
"headers": ["functional"],
}, {
"name": "__cpp_lib_constexpr_numeric",
"values": { "c++2a": int(201911) },
Expand Down