Home | History | Annotate | Download | only in func.not_fn
      1 //===----------------------------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 // UNSUPPORTED: c++98, c++03, c++11, c++14
     11 
     12 // template <class F> unspecified not_fn(F&& f);
     13 
     14 #include <functional>
     15 #include <type_traits>
     16 #include <string>
     17 #include <cassert>
     18 
     19 #include "test_macros.h"
     20 #include "type_id.h"
     21 
     22 
     23 ///////////////////////////////////////////////////////////////////////////////
     24 //                       CALLABLE TEST TYPES
     25 ///////////////////////////////////////////////////////////////////////////////
     26 
     27 bool returns_true() { return true; }
     28 
     29 template <class Ret = bool>
     30 struct MoveOnlyCallable {
     31   MoveOnlyCallable(MoveOnlyCallable const&) = delete;
     32   MoveOnlyCallable(MoveOnlyCallable&& other)
     33       : value(other.value)
     34   { other.value = !other.value; }
     35 
     36   template <class ...Args>
     37   Ret operator()(Args&&...) { return Ret{value}; }
     38 
     39   explicit MoveOnlyCallable(bool x) : value(x) {}
     40   Ret value;
     41 };
     42 
     43 template <class Ret = bool>
     44 struct CopyCallable {
     45   CopyCallable(CopyCallable const& other)
     46       : value(other.value) {}
     47 
     48   CopyCallable(CopyCallable&& other)
     49       : value(other.value) { other.value = !other.value; }
     50 
     51   template <class ...Args>
     52   Ret operator()(Args&&...) { return Ret{value}; }
     53 
     54   explicit CopyCallable(bool x) : value(x)  {}
     55   Ret value;
     56 };
     57 
     58 
     59 template <class Ret = bool>
     60 struct ConstCallable {
     61   ConstCallable(ConstCallable const& other)
     62       : value(other.value) {}
     63 
     64   ConstCallable(ConstCallable&& other)
     65       : value(other.value) { other.value = !other.value; }
     66 
     67   template <class ...Args>
     68   Ret operator()(Args&&...) const { return Ret{value}; }
     69 
     70   explicit ConstCallable(bool x) : value(x)  {}
     71   Ret value;
     72 };
     73 
     74 
     75 
     76 template <class Ret = bool>
     77 struct NoExceptCallable {
     78   NoExceptCallable(NoExceptCallable const& other)
     79       : value(other.value) {}
     80 
     81   template <class ...Args>
     82   Ret operator()(Args&&...) noexcept { return Ret{value}; }
     83 
     84   template <class ...Args>
     85   Ret operator()(Args&&...) const noexcept { return Ret{value}; }
     86 
     87   explicit NoExceptCallable(bool x) : value(x)  {}
     88   Ret value;
     89 };
     90 
     91 struct CopyAssignableWrapper {
     92   CopyAssignableWrapper(CopyAssignableWrapper const&) = default;
     93   CopyAssignableWrapper(CopyAssignableWrapper&&) = default;
     94   CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default;
     95   CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default;
     96 
     97   template <class ...Args>
     98   bool operator()(Args&&...) { return value; }
     99 
    100   explicit CopyAssignableWrapper(bool x) : value(x) {}
    101   bool value;
    102 };
    103 
    104 
    105 struct MoveAssignableWrapper {
    106   MoveAssignableWrapper(MoveAssignableWrapper const&) = delete;
    107   MoveAssignableWrapper(MoveAssignableWrapper&&) = default;
    108   MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete;
    109   MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default;
    110 
    111   template <class ...Args>
    112   bool operator()(Args&&...) { return value; }
    113 
    114   explicit MoveAssignableWrapper(bool x) : value(x) {}
    115   bool value;
    116 };
    117 
    118 struct MemFunCallable {
    119   explicit MemFunCallable(bool x) : value(x) {}
    120 
    121   bool return_value() const { return value; }
    122   bool return_value_nc() { return value; }
    123   bool value;
    124 };
    125 
    126 enum CallType : unsigned {
    127   CT_None,
    128   CT_NonConst = 1,
    129   CT_Const = 2,
    130   CT_LValue = 4,
    131   CT_RValue = 8
    132 };
    133 
    134 inline constexpr CallType operator|(CallType LHS, CallType RHS) {
    135     return static_cast<CallType>(static_cast<unsigned>(LHS) | static_cast<unsigned>(RHS));
    136 }
    137 
    138 struct ForwardingCallObject {
    139 
    140   template <class ...Args>
    141   bool operator()(Args&&...) & {
    142       set_call<Args&&...>(CT_NonConst | CT_LValue);
    143       return true;
    144   }
    145 
    146   template <class ...Args>
    147   bool operator()(Args&&...) const & {
    148       set_call<Args&&...>(CT_Const | CT_LValue);
    149       return true;
    150   }
    151 
    152   // Don't allow the call operator to be invoked as an rvalue.
    153   template <class ...Args>
    154   bool operator()(Args&&...) && {
    155       set_call<Args&&...>(CT_NonConst | CT_RValue);
    156       return true;
    157   }
    158 
    159   template <class ...Args>
    160   bool operator()(Args&&...) const && {
    161       set_call<Args&&...>(CT_Const | CT_RValue);
    162       return true;
    163   }
    164 
    165   template <class ...Args>
    166   static void set_call(CallType type) {
    167       assert(last_call_type == CT_None);
    168       assert(last_call_args == nullptr);
    169       last_call_type = type;
    170       last_call_args = &makeArgumentID<Args...>();
    171   }
    172 
    173   template <class ...Args>
    174   static bool check_call(CallType type) {
    175       bool result =
    176            last_call_type == type
    177         && last_call_args
    178         && *last_call_args == makeArgumentID<Args...>();
    179       last_call_type = CT_None;
    180       last_call_args = nullptr;
    181       return result;
    182   }
    183 
    184   static CallType      last_call_type;
    185   static TypeID const* last_call_args;
    186 };
    187 
    188 CallType ForwardingCallObject::last_call_type = CT_None;
    189 TypeID const* ForwardingCallObject::last_call_args = nullptr;
    190 
    191 
    192 
    193 ///////////////////////////////////////////////////////////////////////////////
    194 //                        BOOL TEST TYPES
    195 ///////////////////////////////////////////////////////////////////////////////
    196 
    197 struct EvilBool {
    198   static int bang_called;
    199 
    200   EvilBool(EvilBool const&) = default;
    201   EvilBool(EvilBool&&) = default;
    202 
    203   friend EvilBool operator!(EvilBool const& other) {
    204     ++bang_called;
    205     return EvilBool{!other.value};
    206   }
    207 
    208 private:
    209   friend struct MoveOnlyCallable<EvilBool>;
    210   friend struct CopyCallable<EvilBool>;
    211   friend struct NoExceptCallable<EvilBool>;
    212 
    213   explicit EvilBool(bool x) : value(x) {}
    214   EvilBool& operator=(EvilBool const& other) = default;
    215 
    216 public:
    217   bool value;
    218 };
    219 
    220 int EvilBool::bang_called = 0;
    221 
    222 struct ExplicitBool {
    223   ExplicitBool(ExplicitBool const&) = default;
    224   ExplicitBool(ExplicitBool&&) = default;
    225 
    226   explicit operator bool() const { return value; }
    227 
    228 private:
    229   friend struct MoveOnlyCallable<ExplicitBool>;
    230   friend struct CopyCallable<ExplicitBool>;
    231 
    232   explicit ExplicitBool(bool x) : value(x) {}
    233   ExplicitBool& operator=(bool x) {
    234       value = x;
    235       return *this;
    236   }
    237 
    238   bool value;
    239 };
    240 
    241 
    242 struct NoExceptEvilBool {
    243   NoExceptEvilBool(NoExceptEvilBool const&) = default;
    244   NoExceptEvilBool(NoExceptEvilBool&&) = default;
    245   NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default;
    246 
    247   explicit NoExceptEvilBool(bool x) : value(x) {}
    248 
    249   friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept {
    250     return NoExceptEvilBool{!other.value};
    251   }
    252 
    253   bool value;
    254 };
    255 
    256 
    257 
    258 void constructor_tests()
    259 {
    260     {
    261         using T = MoveOnlyCallable<bool>;
    262         T value(true);
    263         using RetT = decltype(std::not_fn(std::move(value)));
    264         static_assert(std::is_move_constructible<RetT>::value, "");
    265         static_assert(!std::is_copy_constructible<RetT>::value, "");
    266         static_assert(!std::is_move_assignable<RetT>::value, "");
    267         static_assert(!std::is_copy_assignable<RetT>::value, "");
    268         auto ret = std::not_fn(std::move(value));
    269         // test it was moved from
    270         assert(value.value == false);
    271         // test that ret() negates the original value 'true'
    272         assert(ret() == false);
    273         assert(ret(0, 0.0, "blah") == false);
    274         // Move ret and test that it was moved from and that ret2 got the
    275         // original value.
    276         auto ret2 = std::move(ret);
    277         assert(ret() == true);
    278         assert(ret2() == false);
    279         assert(ret2(42) == false);
    280     }
    281     {
    282         using T = CopyCallable<bool>;
    283         T value(false);
    284         using RetT = decltype(std::not_fn(value));
    285         static_assert(std::is_move_constructible<RetT>::value, "");
    286         static_assert(std::is_copy_constructible<RetT>::value, "");
    287         static_assert(!std::is_move_assignable<RetT>::value, "");
    288         static_assert(!std::is_copy_assignable<RetT>::value, "");
    289         auto ret = std::not_fn(value);
    290         // test that value is unchanged (copied not moved)
    291         assert(value.value == false);
    292         // test 'ret' has the original value
    293         assert(ret() == true);
    294         assert(ret(42, 100) == true);
    295         // move from 'ret' and check that 'ret2' has the original value.
    296         auto ret2 = std::move(ret);
    297         assert(ret() == false);
    298         assert(ret2() == true);
    299         assert(ret2("abc") == true);
    300     }
    301     {
    302         using T = CopyAssignableWrapper;
    303         T value(true);
    304         T value2(false);
    305         using RetT = decltype(std::not_fn(value));
    306         static_assert(std::is_move_constructible<RetT>::value, "");
    307         static_assert(std::is_copy_constructible<RetT>::value, "");
    308         static_assert(std::is_move_assignable<RetT>::value, "");
    309         static_assert(std::is_copy_assignable<RetT>::value, "");
    310         auto ret = std::not_fn(value);
    311         assert(ret() == false);
    312         auto ret2 = std::not_fn(value2);
    313         assert(ret2() == true);
    314         ret = ret2;
    315         assert(ret() == true);
    316         assert(ret2() == true);
    317     }
    318     {
    319         using T = MoveAssignableWrapper;
    320         T value(true);
    321         T value2(false);
    322         using RetT = decltype(std::not_fn(std::move(value)));
    323         static_assert(std::is_move_constructible<RetT>::value, "");
    324         static_assert(!std::is_copy_constructible<RetT>::value, "");
    325         static_assert(std::is_move_assignable<RetT>::value, "");
    326         static_assert(!std::is_copy_assignable<RetT>::value, "");
    327         auto ret = std::not_fn(std::move(value));
    328         assert(ret() == false);
    329         auto ret2 = std::not_fn(std::move(value2));
    330         assert(ret2() == true);
    331         ret = std::move(ret2);
    332         assert(ret() == true);
    333     }
    334 }
    335 
    336 void return_type_tests()
    337 {
    338     using std::is_same;
    339     {
    340         using T = CopyCallable<bool>;
    341         auto ret = std::not_fn(T{false});
    342         static_assert(is_same<decltype(ret()), bool>::value, "");
    343         static_assert(is_same<decltype(ret("abc")), bool>::value, "");
    344         assert(ret() == true);
    345     }
    346     {
    347         using T = CopyCallable<ExplicitBool>;
    348         auto ret = std::not_fn(T{true});
    349         static_assert(is_same<decltype(ret()), bool>::value, "");
    350         static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, "");
    351         assert(ret() == false);
    352     }
    353     {
    354         using T = CopyCallable<EvilBool>;
    355         auto ret = std::not_fn(T{false});
    356         static_assert(is_same<decltype(ret()), EvilBool>::value, "");
    357         EvilBool::bang_called = 0;
    358         auto value_ret = ret();
    359         assert(EvilBool::bang_called == 1);
    360         assert(value_ret.value == true);
    361         ret();
    362         assert(EvilBool::bang_called == 2);
    363     }
    364 }
    365 
    366 // Other tests only test using objects with call operators. Test various
    367 // other callable types here.
    368 void other_callable_types_test()
    369 {
    370     { // test with function pointer
    371         auto ret = std::not_fn(returns_true);
    372         assert(ret() == false);
    373     }
    374     { // test with lambda
    375         auto returns_value = [](bool value) { return value; };
    376         auto ret = std::not_fn(returns_value);
    377         assert(ret(true) == false);
    378         assert(ret(false) == true);
    379     }
    380     { // test with pointer to member function
    381         MemFunCallable mt(true);
    382         const MemFunCallable mf(false);
    383         auto ret = std::not_fn(&MemFunCallable::return_value);
    384         assert(ret(mt) == false);
    385         assert(ret(mf) == true);
    386         assert(ret(&mt) == false);
    387         assert(ret(&mf) == true);
    388     }
    389     { // test with pointer to member function
    390         MemFunCallable mt(true);
    391         MemFunCallable mf(false);
    392         auto ret = std::not_fn(&MemFunCallable::return_value_nc);
    393         assert(ret(mt) == false);
    394         assert(ret(mf) == true);
    395         assert(ret(&mt) == false);
    396         assert(ret(&mf) == true);
    397     }
    398     { // test with pointer to member data
    399         MemFunCallable mt(true);
    400         const MemFunCallable mf(false);
    401         auto ret = std::not_fn(&MemFunCallable::value);
    402         assert(ret(mt) == false);
    403         assert(ret(mf) == true);
    404         assert(ret(&mt) == false);
    405         assert(ret(&mf) == true);
    406     }
    407 }
    408 
    409 void throws_in_constructor_test()
    410 {
    411 #ifndef TEST_HAS_NO_EXCEPTIONS
    412     struct ThrowsOnCopy {
    413       ThrowsOnCopy(ThrowsOnCopy const&) {
    414         throw 42;
    415       }
    416       ThrowsOnCopy() = default;
    417       bool operator()() const {
    418         assert(false);
    419 #if defined(_LIBCPP_MSVC)
    420         __assume(0);
    421 #else
    422         __builtin_unreachable();
    423 #endif
    424       }
    425     };
    426     {
    427         ThrowsOnCopy cp;
    428         try {
    429             std::not_fn(cp);
    430             assert(false);
    431         } catch (int const& value) {
    432             assert(value == 42);
    433         }
    434     }
    435 #endif
    436 }
    437 
    438 void call_operator_sfinae_test() {
    439     { // wrong number of arguments
    440         using T = decltype(std::not_fn(returns_true));
    441         static_assert(std::is_callable<T()>::value, ""); // callable only with no args
    442         static_assert(!std::is_callable<T(bool)>::value, "");
    443     }
    444     { // violates const correctness (member function pointer)
    445         using T = decltype(std::not_fn(&MemFunCallable::return_value_nc));
    446         static_assert(std::is_callable<T(MemFunCallable&)>::value, "");
    447         static_assert(!std::is_callable<T(const MemFunCallable&)>::value, "");
    448     }
    449     { // violates const correctness (call object)
    450         using Obj = CopyCallable<bool>;
    451         using NCT = decltype(std::not_fn(Obj{true}));
    452         using CT = const NCT;
    453         static_assert(std::is_callable<NCT()>::value, "");
    454         static_assert(!std::is_callable<CT()>::value, "");
    455     }
    456     { // returns bad type with no operator!
    457         auto fn = [](auto x) { return x; };
    458         using T = decltype(std::not_fn(fn));
    459         static_assert(std::is_callable<T(bool)>::value, "");
    460         static_assert(!std::is_callable<T(std::string)>::value, "");
    461     }
    462 }
    463 
    464 void call_operator_forwarding_test()
    465 {
    466     using Fn = ForwardingCallObject;
    467     auto obj = std::not_fn(Fn{});
    468     const auto& c_obj = obj;
    469     { // test zero args
    470         obj();
    471         assert(Fn::check_call<>(CT_NonConst | CT_LValue));
    472         std::move(obj)();
    473         assert(Fn::check_call<>(CT_NonConst | CT_RValue));
    474         c_obj();
    475         assert(Fn::check_call<>(CT_Const | CT_LValue));
    476         std::move(c_obj)();
    477         assert(Fn::check_call<>(CT_Const | CT_RValue));
    478     }
    479     { // test value categories
    480         int x = 42;
    481         const int cx = 42;
    482         obj(x);
    483         assert(Fn::check_call<int&>(CT_NonConst | CT_LValue));
    484         obj(cx);
    485         assert(Fn::check_call<const int&>(CT_NonConst | CT_LValue));
    486         obj(std::move(x));
    487         assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
    488         obj(std::move(cx));
    489         assert(Fn::check_call<const int&&>(CT_NonConst | CT_LValue));
    490         obj(42);
    491         assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
    492     }
    493     { // test value categories - rvalue
    494         int x = 42;
    495         const int cx = 42;
    496         std::move(obj)(x);
    497         assert(Fn::check_call<int&>(CT_NonConst | CT_RValue));
    498         std::move(obj)(cx);
    499         assert(Fn::check_call<const int&>(CT_NonConst | CT_RValue));
    500         std::move(obj)(std::move(x));
    501         assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue));
    502         std::move(obj)(std::move(cx));
    503         assert(Fn::check_call<const int&&>(CT_NonConst | CT_RValue));
    504         std::move(obj)(42);
    505         assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue));
    506     }
    507     { // test value categories - const call
    508         int x = 42;
    509         const int cx = 42;
    510         c_obj(x);
    511         assert(Fn::check_call<int&>(CT_Const | CT_LValue));
    512         c_obj(cx);
    513         assert(Fn::check_call<const int&>(CT_Const | CT_LValue));
    514         c_obj(std::move(x));
    515         assert(Fn::check_call<int&&>(CT_Const | CT_LValue));
    516         c_obj(std::move(cx));
    517         assert(Fn::check_call<const int&&>(CT_Const | CT_LValue));
    518         c_obj(42);
    519         assert(Fn::check_call<int&&>(CT_Const | CT_LValue));
    520     }
    521     { // test value categories - const call rvalue
    522         int x = 42;
    523         const int cx = 42;
    524         std::move(c_obj)(x);
    525         assert(Fn::check_call<int&>(CT_Const | CT_RValue));
    526         std::move(c_obj)(cx);
    527         assert(Fn::check_call<const int&>(CT_Const | CT_RValue));
    528         std::move(c_obj)(std::move(x));
    529         assert(Fn::check_call<int&&>(CT_Const | CT_RValue));
    530         std::move(c_obj)(std::move(cx));
    531         assert(Fn::check_call<const int&&>(CT_Const | CT_RValue));
    532         std::move(c_obj)(42);
    533         assert(Fn::check_call<int&&>(CT_Const | CT_RValue));
    534     }
    535     { // test multi arg
    536         const double y = 3.14;
    537         std::string s = "abc";
    538         obj(42, std::move(y), s, std::string{"foo"});
    539         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_LValue);
    540         std::move(obj)(42, std::move(y), s, std::string{"foo"});
    541         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_RValue);
    542         c_obj(42, std::move(y), s, std::string{"foo"});
    543         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const  | CT_LValue);
    544         std::move(c_obj)(42, std::move(y), s, std::string{"foo"});
    545         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const  | CT_RValue);
    546     }
    547 }
    548 
    549 void call_operator_noexcept_test()
    550 {
    551     {
    552         using T = ConstCallable<bool>;
    553         T value(true);
    554         auto ret = std::not_fn(value);
    555         static_assert(!noexcept(ret()), "call should not be noexcept");
    556         auto const& cret = ret;
    557         static_assert(!noexcept(cret()), "call should not be noexcept");
    558     }
    559     {
    560         using T = NoExceptCallable<bool>;
    561         T value(true);
    562         auto ret = std::not_fn(value);
    563         LIBCPP_STATIC_ASSERT(noexcept(!_VSTD::__invoke(value)), "");
    564 #if TEST_STD_VER > 14
    565         static_assert(noexcept(!std::invoke(value)), "");
    566 #endif
    567         static_assert(noexcept(ret()), "call should be noexcept");
    568         auto const& cret = ret;
    569         static_assert(noexcept(cret()), "call should be noexcept");
    570     }
    571     {
    572         using T = NoExceptCallable<NoExceptEvilBool>;
    573         T value(true);
    574         auto ret = std::not_fn(value);
    575         static_assert(noexcept(ret()), "call should not be noexcept");
    576         auto const& cret = ret;
    577         static_assert(noexcept(cret()), "call should not be noexcept");
    578     }
    579     {
    580         using T = NoExceptCallable<EvilBool>;
    581         T value(true);
    582         auto ret = std::not_fn(value);
    583         static_assert(!noexcept(ret()), "call should not be noexcept");
    584         auto const& cret = ret;
    585         static_assert(!noexcept(cret()), "call should not be noexcept");
    586     }
    587 }
    588 
    589 void test_lwg2767() {
    590     // See http://wg21.link/LWG2767
    591     struct Abstract { virtual void f() const = 0; };
    592     struct Derived : public Abstract { void f() const {} };
    593     struct F { bool operator()(Abstract&&) { return false; } };
    594     {
    595         Derived d;
    596         Abstract &a = d;
    597         bool b = std::not_fn(F{})(std::move(a));
    598         assert(b);
    599     }
    600 }
    601 
    602 int main()
    603 {
    604     constructor_tests();
    605     return_type_tests();
    606     other_callable_types_test();
    607     throws_in_constructor_test();
    608     call_operator_sfinae_test(); // somewhat of an extension
    609     call_operator_forwarding_test();
    610     call_operator_noexcept_test();
    611     test_lwg2767();
    612 }
    613