|
@@ -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>, "");
|
|
|
+ }
|
|
|
+}
|