brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.4 KiB · 54499c0 Raw
426 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 11// <functional>12 13// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS14// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS15 16// template<class F, class... Args>17// invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) // C++1718//     noexcept(is_nothrow_invocable_v<_Fn, _Args...>);19 20/// C++14 [func.def] 20.9.021/// (1) The following definitions apply to this Clause:22/// (2) A call signature is the name of a return type followed by a parenthesized23///     comma-separated list of zero or more argument types.24/// (3) A callable type is a function object type (20.9) or a pointer to member.25/// (4) A callable object is an object of a callable type.26/// (5) A call wrapper type is a type that holds a callable object and supports27///     a call operation that forwards to that object.28/// (6) A call wrapper is an object of a call wrapper type.29/// (7) A target object is the callable object held by a call wrapper.30 31/// C++14 [func.require] 20.9.132///33/// Define INVOKE (f, t1, t2, ..., tN) as follows:34///   (1.1) - (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of35///   type T or a reference to an object of type T or a reference to an object of a type derived from T;36///   (1.2) - ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of37///   the types described in the previous item;38///   (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 a39///   reference to an object of type T or a reference to an object of a type derived from T;40///   (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 types41///   described in the previous item;42///   (1.5) - f(t1, t2, ..., tN) in all other cases.43 44#include <functional>45#include <type_traits>46#include <utility> // for std::move47#include <cassert>48 49#include "test_macros.h"50 51struct NonCopyable {52    NonCopyable() {}53private:54    NonCopyable(NonCopyable const&) = delete;55    NonCopyable& operator=(NonCopyable const&) = delete;56};57 58struct TestClass {59    explicit TestClass(int x) : data(x) {}60 61    int& operator()(NonCopyable&&) & { return data; }62    int const& operator()(NonCopyable&&) const & { return data; }63    int volatile& operator()(NonCopyable&&) volatile & { return data; }64    int const volatile& operator()(NonCopyable&&) const volatile & { return data; }65 66    int&& operator()(NonCopyable&&) && { return std::move(data); }67    int const&& operator()(NonCopyable&&) const && { return std::move(data); }68    int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); }69    int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); }70 71    int data;72private:73    TestClass(TestClass const&) = delete;74    TestClass& operator=(TestClass const&) = delete;75};76 77struct DerivedFromTestClass : public TestClass {78    explicit DerivedFromTestClass(int x) : TestClass(x) {}79};80 81int& foo(NonCopyable&&) {82    static int data = 42;83    return data;84}85 86template <class Signature,  class Expect, class Functor>87void test_b12(Functor&& f) {88    // Create the callable object.89    typedef Signature TestClass::*ClassFunc;90    ClassFunc func_ptr = &TestClass::operator();91 92    // Create the dummy arg.93    NonCopyable arg;94 95    // Check that the deduced return type of invoke is what is expected.96    typedef decltype(97        std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg))98    ) DeducedReturnType;99    static_assert((std::is_same<DeducedReturnType, Expect>::value), "");100 101    // Check that result_of_t matches Expect.102    typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type103      ResultOfReturnType;104    static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");105 106    // Run invoke and check the return value.107    DeducedReturnType ret =108            std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg));109    assert(ret == 42);110}111 112template <class Expect, class Functor>113void test_b34(Functor&& f) {114    // Create the callable object.115    typedef int TestClass::*ClassFunc;116    ClassFunc func_ptr = &TestClass::data;117 118    // Check that the deduced return type of invoke is what is expected.119    typedef decltype(120        std::invoke(func_ptr, std::forward<Functor>(f))121    ) DeducedReturnType;122    static_assert((std::is_same<DeducedReturnType, Expect>::value), "");123 124    // Check that result_of_t matches Expect.125    typedef typename std::result_of<ClassFunc&&(Functor&&)>::type126            ResultOfReturnType;127    static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");128 129    // Run invoke and check the return value.130    DeducedReturnType ret =131            std::invoke(func_ptr, std::forward<Functor>(f));132    assert(ret == 42);133}134 135template <class Expect, class Functor>136void test_b5(Functor&& f) {137    NonCopyable arg;138 139    // Check that the deduced return type of invoke is what is expected.140    typedef decltype(141        std::invoke(std::forward<Functor>(f), std::move(arg))142    ) DeducedReturnType;143    static_assert((std::is_same<DeducedReturnType, Expect>::value), "");144 145    // Check that result_of_t matches Expect.146    typedef typename std::result_of<Functor&&(NonCopyable&&)>::type147            ResultOfReturnType;148    static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");149 150    // Run invoke and check the return value.151    DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg));152    assert(ret == 42);153}154 155void bullet_one_two_tests() {156    {157        TestClass cl(42);158        test_b12<int&(NonCopyable&&) &, int&>(cl);159        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);160        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);161        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);162 163        test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));164        test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));165        test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));166        test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));167    }168    {169        DerivedFromTestClass cl(42);170        test_b12<int&(NonCopyable&&) &, int&>(cl);171        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);172        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);173        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);174 175        test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));176        test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));177        test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));178        test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));179    }180    {181        TestClass cl_obj(42);182        std::reference_wrapper<TestClass> cl(cl_obj);183        test_b12<int&(NonCopyable&&) &, int&>(cl);184        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);185        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);186        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);187 188        test_b12<int&(NonCopyable&&) &, int&>(std::move(cl));189        test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl));190        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl));191        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl));192    }193    {194        DerivedFromTestClass cl_obj(42);195        std::reference_wrapper<DerivedFromTestClass> cl(cl_obj);196        test_b12<int&(NonCopyable&&) &, int&>(cl);197        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);198        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);199        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);200 201        test_b12<int&(NonCopyable&&) &, int&>(std::move(cl));202        test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl));203        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl));204        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl));205    }206    {207        TestClass cl_obj(42);208        TestClass *cl = &cl_obj;209        test_b12<int&(NonCopyable&&) &, int&>(cl);210        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);211        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);212        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);213    }214    {215        DerivedFromTestClass cl_obj(42);216        DerivedFromTestClass *cl = &cl_obj;217        test_b12<int&(NonCopyable&&) &, int&>(cl);218        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);219        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);220        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);221    }222}223 224void bullet_three_four_tests() {225    {226        typedef TestClass Fn;227        Fn cl(42);228        test_b34<int&>(cl);229        test_b34<int const&>(static_cast<Fn const&>(cl));230        test_b34<int volatile&>(static_cast<Fn volatile&>(cl));231        test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));232 233        test_b34<int&&>(static_cast<Fn &&>(cl));234        test_b34<int const&&>(static_cast<Fn const&&>(cl));235        test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));236        test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));237    }238    {239        typedef DerivedFromTestClass Fn;240        Fn cl(42);241        test_b34<int&>(cl);242        test_b34<int const&>(static_cast<Fn const&>(cl));243        test_b34<int volatile&>(static_cast<Fn volatile&>(cl));244        test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));245 246        test_b34<int&&>(static_cast<Fn &&>(cl));247        test_b34<int const&&>(static_cast<Fn const&&>(cl));248        test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));249        test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));250    }251    {252        typedef TestClass Fn;253        Fn cl(42);254        test_b34<int&>(std::reference_wrapper<Fn>(cl));255        test_b34<int const&>(std::reference_wrapper<Fn const>(cl));256        test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl));257        test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl));258    }259    {260        typedef DerivedFromTestClass Fn;261        Fn cl(42);262        test_b34<int&>(std::reference_wrapper<Fn>(cl));263        test_b34<int const&>(std::reference_wrapper<Fn const>(cl));264        test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl));265        test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl));266    }267    {268        typedef TestClass Fn;269        Fn cl_obj(42);270        Fn* cl = &cl_obj;271        test_b34<int&>(cl);272        test_b34<int const&>(static_cast<Fn const*>(cl));273        test_b34<int volatile&>(static_cast<Fn volatile*>(cl));274        test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));275    }276    {277        typedef DerivedFromTestClass Fn;278        Fn cl_obj(42);279        Fn* cl = &cl_obj;280        test_b34<int&>(cl);281        test_b34<int const&>(static_cast<Fn const*>(cl));282        test_b34<int volatile&>(static_cast<Fn volatile*>(cl));283        test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));284    }285}286 287void bullet_five_tests() {288    using FooType = int&(NonCopyable&&);289    {290        FooType& fn = foo;291        test_b5<int &>(fn);292    }293    {294        FooType* fn = foo;295        test_b5<int &>(fn);296    }297    {298        typedef TestClass Fn;299        Fn cl(42);300        test_b5<int&>(cl);301        test_b5<int const&>(static_cast<Fn const&>(cl));302        test_b5<int volatile&>(static_cast<Fn volatile&>(cl));303        test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl));304 305        test_b5<int&&>(static_cast<Fn &&>(cl));306        test_b5<int const&&>(static_cast<Fn const&&>(cl));307        test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl));308        test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl));309    }310}311 312struct CopyThrows {313  CopyThrows() {}314  CopyThrows(CopyThrows const&) {}315  CopyThrows(CopyThrows&&) noexcept {}316};317 318struct NoThrowCallable {319  void operator()() noexcept {}320  void operator()(CopyThrows) noexcept {}321};322 323struct ThrowsCallable {324  void operator()() {}325};326 327struct MemberObj {328  int x;329};330 331void noexcept_test() {332    {333        NoThrowCallable obj; ((void)obj); // suppress unused warning334        CopyThrows arg; ((void)arg); // suppress unused warning335        static_assert(noexcept(std::invoke(obj)), "");336        static_assert(!noexcept(std::invoke(obj, arg)), "");337        static_assert(noexcept(std::invoke(obj, std::move(arg))), "");338    }339    {340        ThrowsCallable obj; ((void)obj); // suppress unused warning341        static_assert(!noexcept(std::invoke(obj)), "");342    }343    {344        MemberObj obj{42}; ((void)obj); // suppress unused warning.345        static_assert(noexcept(std::invoke(&MemberObj::x, obj)), "");346    }347}348 349// LWG3655: The INVOKE operation and union types350void union_tests() {351    union Union {352        int x;353        int f() { return 42; }354        int g() const { return 52; }355    };356 357    // With a data member358    {359        auto get = []() -> Union { return Union{.x = 3}; };360        int result = std::invoke(&Union::x, get());361        assert(result == 3);362    }363    {364        auto get = []() -> Union const { return Union{.x = 3}; };365        int result = std::invoke(&Union::x, get());366        assert(result == 3);367    }368    {369        Union u{3};370        int& result = std::invoke(&Union::x, u);371        assert(&result == &u.x);372    }373    {374        Union const u{3};375        int const& result = std::invoke(&Union::x, u);376        assert(&result == &u.x);377    }378 379    // With a pointer to a member function380    {381        auto get = []() -> Union { return Union{.x = 3}; };382        int result = std::invoke(&Union::f, get());383        assert(result == 42);384    }385    {386        Union u{3};387        int result = std::invoke(&Union::f, u);388        assert(result == 42);389    }390    {391        // constness mismatch392        static_assert(!std::is_invocable_v<int (Union::*)(), Union const>);393        static_assert(!std::is_invocable_v<int (Union::*)(), Union const&>);394    }395 396    {397        auto get = []() -> Union { return Union{.x = 3}; };398        int result = std::invoke(&Union::g, get());399        assert(result == 52);400    }401    {402        auto get = []() -> Union const { return Union{.x = 3}; };403        int result = std::invoke(&Union::g, get());404        assert(result == 52);405    }406    {407        Union u{3};408        int result = std::invoke(&Union::g, u);409        assert(result == 52);410    }411    {412        Union const u{3};413        int result = std::invoke(&Union::g, u);414        assert(result == 52);415    }416}417 418int main(int, char**) {419    bullet_one_two_tests();420    bullet_three_four_tests();421    bullet_five_tests();422    noexcept_test();423 424  return 0;425}426