//===----------------------------------------------------------------------===// // // 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 // is_invocable_r #include // Non-invocable types 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); // Result type matches template T Return(); 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); // void result type // Any actual return type should be useable with a result type of void. 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); // const- and volatile-qualified void should work too. 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); // Conversion of result type // It should be possible to use a result type to which the actual return type // can be converted. 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); // But not a result type where the conversion doesn't work. static_assert(!std::is_invocable_r)>::value); static_assert(!std::is_invocable_r)>::value); // Non-moveable result type // Define a type that can't be move-constructed. struct CantMove { CantMove() = default; CantMove(CantMove&&) = delete; }; static_assert(!std::is_move_constructible_v); static_assert(!std::is_copy_constructible_v); // Define functions that return that type. CantMove MakeCantMove() { return {}; } CantMove MakeCantMoveWithArg(int) { return {}; } // Assumption check: it should be possible to call one of those functions and // use it to initialize a CantMove object. CantMove cant_move = MakeCantMove(); // Therefore std::is_invocable_r should agree that they can be invoked to yield // a CantMove. static_assert(std::is_invocable_r::value); static_assert(std::is_invocable_r::value); // Of course it still shouldn't be possible to call one of the functions and get // back some other type. static_assert(!std::is_invocable_r::value); // And the argument types should still be important. static_assert(!std::is_invocable_r::value); static_assert(!std::is_invocable_r::value); // is_invocable_r // The struct form should be available too, not just the _v variant. static_assert(std::is_invocable_r)>::value); static_assert(!std::is_invocable_r)>::value);