diff options
Diffstat (limited to 'test/std/utilities/meta/meta.rel/is_invocable.pass.cpp')
-rw-r--r-- | test/std/utilities/meta/meta.rel/is_invocable.pass.cpp | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp b/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp new file mode 100644 index 000000000..1b2a9286f --- /dev/null +++ b/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp @@ -0,0 +1,166 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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. + +#include <type_traits> +#include <functional> +#include <memory> + +#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; } +}; + +int main() +{ + { + using Fn = int(Tag::*)(int); + using RFn = int(Tag::*)(int) &&; + // INVOKE bullet 1, 2 and 3 + { + // Bullet 1 + static_assert(std::is_invocable<Fn, Tag&, int>::value, ""); + static_assert(std::is_invocable<Fn, DerFromTag&, int>::value, ""); + static_assert(std::is_invocable<RFn, Tag&&, int>::value, ""); + static_assert(!std::is_invocable<RFn, Tag&, int>::value, ""); + static_assert(!std::is_invocable<Fn, Tag&>::value, ""); + static_assert(!std::is_invocable<Fn, Tag const&, int>::value, ""); + } + { + // Bullet 2 + using T = std::reference_wrapper<Tag>; + using DT = std::reference_wrapper<DerFromTag>; + using CT = std::reference_wrapper<const Tag>; + static_assert(std::is_invocable<Fn, T&, int>::value, ""); + static_assert(std::is_invocable<Fn, DT&, int>::value, ""); + static_assert(std::is_invocable<Fn, const T&, int>::value, ""); + static_assert(std::is_invocable<Fn, T&&, int>::value, ""); + static_assert(!std::is_invocable<Fn, CT&, int>::value, ""); + static_assert(!std::is_invocable<RFn, T, int>::value, ""); + } + { + // Bullet 3 + using T = Tag*; + using DT = DerFromTag*; + using CT = const Tag*; + using ST = std::unique_ptr<Tag>; + static_assert(std::is_invocable<Fn, T&, int>::value, ""); + static_assert(std::is_invocable<Fn, DT&, int>::value, ""); + static_assert(std::is_invocable<Fn, const T&, int>::value, ""); + static_assert(std::is_invocable<Fn, T&&, int>::value, ""); + static_assert(std::is_invocable<Fn, ST, int>::value, ""); + static_assert(!std::is_invocable<Fn, CT&, int>::value, ""); + static_assert(!std::is_invocable<RFn, T, int>::value, ""); + } + } + { + // Bullets 4, 5 and 6 + using Fn = int (Tag::*); + static_assert(!std::is_invocable<Fn>::value, ""); + { + // Bullet 4 + static_assert(std::is_invocable<Fn, Tag&>::value, ""); + static_assert(std::is_invocable<Fn, DerFromTag&>::value, ""); + static_assert(std::is_invocable<Fn, Tag&&>::value, ""); + static_assert(std::is_invocable<Fn, Tag const&>::value, ""); + } + { + // Bullet 5 + using T = std::reference_wrapper<Tag>; + using DT = std::reference_wrapper<DerFromTag>; + using CT = std::reference_wrapper<const Tag>; + static_assert(std::is_invocable<Fn, T&>::value, ""); + static_assert(std::is_invocable<Fn, DT&>::value, ""); + static_assert(std::is_invocable<Fn, const T&>::value, ""); + static_assert(std::is_invocable<Fn, T&&>::value, ""); + static_assert(std::is_invocable<Fn, CT&>::value, ""); + } + { + // Bullet 6 + using T = Tag*; + using DT = DerFromTag*; + using CT = const Tag*; + using ST = std::unique_ptr<Tag>; + static_assert(std::is_invocable<Fn, T&>::value, ""); + static_assert(std::is_invocable<Fn, DT&>::value, ""); + static_assert(std::is_invocable<Fn, const T&>::value, ""); + static_assert(std::is_invocable<Fn, T&&>::value, ""); + static_assert(std::is_invocable<Fn, ST>::value, ""); + static_assert(std::is_invocable<Fn, CT&>::value, ""); + } + } + { + // INVOKE bullet 7 + { + // Function pointer + using Fp = void(*)(Tag&, int); + static_assert(std::is_invocable<Fp, Tag&, int>::value, ""); + static_assert(std::is_invocable<Fp, DerFromTag&, int>::value, ""); + static_assert(!std::is_invocable<Fp, const Tag&, int>::value, ""); + static_assert(!std::is_invocable<Fp>::value, ""); + static_assert(!std::is_invocable<Fp, Tag&>::value, ""); + } + { + // Function reference + using Fp = void(&)(Tag&, int); + static_assert(std::is_invocable<Fp, Tag&, int>::value, ""); + static_assert(std::is_invocable<Fp, DerFromTag&, int>::value, ""); + static_assert(!std::is_invocable<Fp, const Tag&, int>::value, ""); + static_assert(!std::is_invocable<Fp>::value, ""); + static_assert(!std::is_invocable<Fp, Tag&>::value, ""); + } + { + // Function object + using Fn = NotCallableWithInt; + static_assert(std::is_invocable<Fn, Tag>::value, ""); + static_assert(!std::is_invocable<Fn, int>::value, ""); + } + } + { + // Check that the conversion to the return type is properly checked + using Fn = int(*)(); + static_assert(std::is_invocable_r<Implicit, Fn>::value, ""); + static_assert(std::is_invocable_r<double, Fn>::value, ""); + static_assert(std::is_invocable_r<const volatile void, Fn>::value, ""); + static_assert(!std::is_invocable_r<Explicit, Fn>::value, ""); + } + { + // Check for is_invocable_v + using Fn = void(*)(); + static_assert(std::is_invocable_v<Fn>, ""); + static_assert(!std::is_invocable_v<Fn, int>, ""); + } + { + // Check for is_invocable_r_v + using Fn = void(*)(); + static_assert(std::is_invocable_r_v<void, Fn>, ""); + static_assert(!std::is_invocable_r_v<int, Fn>, ""); + } +} |