1 //===- TypeTraitsTest.cpp - type_traits unit tests ------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/ADT/STLExtras.h"
10 #include "gtest/gtest.h"
11 
12 using namespace llvm;
13 
14 //===----------------------------------------------------------------------===//
15 // function_traits
16 //===----------------------------------------------------------------------===//
17 
18 namespace {
19 /// Check a callable type of the form `bool(const int &)`.
20 template <typename CallableT> struct CheckFunctionTraits {
21   static_assert(
22       std::is_same<typename function_traits<CallableT>::result_t, bool>::value,
23       "expected result_t to be `bool`");
24   static_assert(
25       std::is_same<typename function_traits<CallableT>::template arg_t<0>,
26                    const int &>::value,
27       "expected arg_t<0> to be `const int &`");
28   static_assert(function_traits<CallableT>::num_args == 1,
29                 "expected num_args to be 1");
30 };
31 
32 /// Test function pointers.
33 using FuncType = bool (*)(const int &);
34 struct CheckFunctionPointer : CheckFunctionTraits<FuncType> {};
35 
36 static bool func(const int &v);
37 struct CheckFunctionPointer2 : CheckFunctionTraits<decltype(&func)> {};
38 
39 /// Test method pointers.
40 struct Foo {
41   bool func(const int &v);
42 };
43 struct CheckMethodPointer : CheckFunctionTraits<decltype(&Foo::func)> {};
44 
45 /// Test lambda references.
46 auto lambdaFunc = [](const int &v) -> bool { return true; };
47 struct CheckLambda : CheckFunctionTraits<decltype(lambdaFunc)> {};
48 
49 } // end anonymous namespace
50 
51 //===----------------------------------------------------------------------===//
52 // is_detected
53 //===----------------------------------------------------------------------===//
54 
55 namespace {
56 struct HasFooMethod {
57   void foo() {}
58 };
59 struct NoFooMethod {};
60 
61 template <class T> using has_foo_method_t = decltype(std::declval<T &>().foo());
62 
63 static_assert(is_detected<has_foo_method_t, HasFooMethod>::value,
64               "expected foo method to be detected");
65 static_assert(!is_detected<has_foo_method_t, NoFooMethod>::value,
66               "expected no foo method to be detected");
67 } // end anonymous namespace
68 
69 //===----------------------------------------------------------------------===//
70 // is_invocable
71 //===----------------------------------------------------------------------===//
72 
73 static void invocable_fn(int) {}
74 
75 static_assert(is_invocable<decltype(invocable_fn), int>::value,
76               "expected function to be invocable");
77 static_assert(!is_invocable<decltype(invocable_fn), void *>::value,
78               "expected function not to be invocable");
79 static_assert(!is_invocable<decltype(invocable_fn), int, int>::value,
80               "expected function not to be invocable");
81