//===----------------------------------------------------------------------===// // // 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++98, c++03, c++11, c++14 // type_traits // is_invocable // Most testing of is_invocable is done within the [meta.trans.other] result_of // tests. // Fn and all types in the template parameter pack ArgTypes shall be // complete types, cv void, or arrays of unknown bound. #include #include #include #include #include "test_macros.h" struct Tag {}; struct DerFromTag : Tag {}; struct Implicit { Implicit(int) {} }; struct Explicit { explicit Explicit(int) {} }; struct NotCallableWithInt { int operator()(int) = delete; int operator()(Tag) { return 42; } }; struct Sink { template void operator()(Args&&...) const {} }; int main(int, char**) { using AbominableFunc = void(...) const; // Non-callable things { static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable >::value, ""); static_assert(!std::is_invocable >::value, ""); static_assert(!std::is_invocable >::value, ""); static_assert(!std::is_invocable::value, ""); // with parameters static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r >::value, ""); static_assert(!std::is_invocable_r >::value, ""); static_assert(!std::is_invocable_r >::value, ""); static_assert(!std::is_invocable_r::value, ""); // with parameters static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); } { using Fn = int (Tag::*)(int); using RFn = int (Tag::*)(int)&&; // INVOKE bullet 1, 2 and 3 { // Bullet 1 static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); } { // Bullet 2 using T = std::reference_wrapper; using DT = std::reference_wrapper; using CT = std::reference_wrapper; static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); } { // Bullet 3 using T = Tag*; using DT = DerFromTag*; using CT = const Tag*; using ST = std::unique_ptr; static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); } } { // Bullets 4, 5 and 6 using Fn = int(Tag::*); static_assert(!std::is_invocable::value, ""); { // Bullet 4 static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); } { // Bullet 5 using T = std::reference_wrapper; using DT = std::reference_wrapper; using CT = std::reference_wrapper; static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); } { // Bullet 6 using T = Tag*; using DT = DerFromTag*; using CT = const Tag*; using ST = std::unique_ptr; static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); } } { // INVOKE bullet 7 {// Function pointer using Fp = void(*)(Tag&, int); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); } { // Function reference using Fp = void (&)(Tag&, int); static_assert(std::is_invocable::value, ""); static_assert(std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); } { // Function object using Fn = NotCallableWithInt; static_assert(std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); } } { // Check that the conversion to the return type is properly checked using Fn = int (*)(); static_assert(std::is_invocable_r::value, ""); static_assert(std::is_invocable_r::value, ""); static_assert(std::is_invocable_r::value, ""); static_assert(!std::is_invocable_r::value, ""); } { // Check for is_invocable_v using Fn = void (*)(); static_assert(std::is_invocable_v, ""); static_assert(!std::is_invocable_v, ""); } { // Check for is_invocable_r_v using Fn = void (*)(); static_assert(std::is_invocable_r_v, ""); static_assert(!std::is_invocable_r_v, ""); } return 0; }