245 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 11// type_traits12 13// is_invocable14 15// Most testing of is_invocable is done within the [meta.trans.other] result_of16// tests.17 18// Fn and all types in the template parameter pack ArgTypes shall be19// complete types, cv void, or arrays of unknown bound.20 21#include <cstddef>22#include <functional>23#include <memory>24#include <type_traits>25#include <vector>26 27struct Tag {};28struct DerFromTag : Tag {};29 30struct Implicit {31 Implicit(int) {}32};33 34struct Explicit {35 explicit Explicit(int) {}36};37 38struct NotCallableWithInt {39 int operator()(int) = delete;40 int operator()(Tag) { return 42; }41};42 43struct Sink {44 template <class ...Args>45 void operator()(Args&&...) const {}46};47 48int main(int, char**) {49 using AbominableFunc = void(...) const;50 51 // Non-callable things52 {53 static_assert(!std::is_invocable<void>::value, "");54 static_assert(!std::is_invocable<const void>::value, "");55 static_assert(!std::is_invocable<volatile void>::value, "");56 static_assert(!std::is_invocable<const volatile void>::value, "");57 static_assert(!std::is_invocable<std::nullptr_t>::value, "");58 static_assert(!std::is_invocable<int>::value, "");59 static_assert(!std::is_invocable<double>::value, "");60 61 static_assert(!std::is_invocable<int[]>::value, "");62 static_assert(!std::is_invocable<int[3]>::value, "");63 64 static_assert(!std::is_invocable<int*>::value, "");65 static_assert(!std::is_invocable<const int*>::value, "");66 static_assert(!std::is_invocable<int const*>::value, "");67 68 static_assert(!std::is_invocable<int&>::value, "");69 static_assert(!std::is_invocable<const int&>::value, "");70 static_assert(!std::is_invocable<int&&>::value, "");71 72 static_assert(!std::is_invocable<std::vector<int> >::value, "");73 static_assert(!std::is_invocable<std::vector<int*> >::value, "");74 static_assert(!std::is_invocable<std::vector<int**> >::value, "");75 76 static_assert(!std::is_invocable<AbominableFunc>::value, "");77 78 // with parameters79 static_assert(!std::is_invocable<int, int>::value, "");80 static_assert(!std::is_invocable<int, double, float>::value, "");81 static_assert(!std::is_invocable<int, char, float, double>::value, "");82 static_assert(!std::is_invocable<Sink, AbominableFunc>::value, "");83 static_assert(!std::is_invocable<Sink, void>::value, "");84 static_assert(!std::is_invocable<Sink, const volatile void>::value,85 "");86 87 88 static_assert(!std::is_invocable_r<int, void>::value, "");89 static_assert(!std::is_invocable_r<int, const void>::value, "");90 static_assert(!std::is_invocable_r<int, volatile void>::value, "");91 static_assert(!std::is_invocable_r<int, const volatile void>::value, "");92 static_assert(!std::is_invocable_r<int, std::nullptr_t>::value, "");93 static_assert(!std::is_invocable_r<int, int>::value, "");94 static_assert(!std::is_invocable_r<int, double>::value, "");95 96 static_assert(!std::is_invocable_r<int, int[]>::value, "");97 static_assert(!std::is_invocable_r<int, int[3]>::value, "");98 99 static_assert(!std::is_invocable_r<int, int*>::value, "");100 static_assert(!std::is_invocable_r<int, const int*>::value, "");101 static_assert(!std::is_invocable_r<int, int const*>::value, "");102 103 static_assert(!std::is_invocable_r<int, int&>::value, "");104 static_assert(!std::is_invocable_r<int, const int&>::value, "");105 static_assert(!std::is_invocable_r<int, int&&>::value, "");106 107 static_assert(!std::is_invocable_r<int, std::vector<int> >::value, "");108 static_assert(!std::is_invocable_r<int, std::vector<int*> >::value, "");109 static_assert(!std::is_invocable_r<int, std::vector<int**> >::value, "");110 static_assert(!std::is_invocable_r<void, AbominableFunc>::value, "");111 112 // with parameters113 static_assert(!std::is_invocable_r<int, int, int>::value, "");114 static_assert(!std::is_invocable_r<int, int, double, float>::value, "");115 static_assert(!std::is_invocable_r<int, int, char, float, double>::value,116 "");117 static_assert(!std::is_invocable_r<void, Sink, AbominableFunc>::value, "");118 static_assert(!std::is_invocable_r<void, Sink, void>::value, "");119 static_assert(!std::is_invocable_r<void, Sink, const volatile void>::value,120 "");121 }122 {123 using Fn = int (Tag::*)(int);124 using RFn = int (Tag::*)(int)&&;125 // INVOKE bullet 1, 2 and 3126 {127 // Bullet 1128 static_assert(std::is_invocable<Fn, Tag&, int>::value, "");129 static_assert(std::is_invocable<Fn, DerFromTag&, int>::value, "");130 static_assert(std::is_invocable<RFn, Tag&&, int>::value, "");131 static_assert(!std::is_invocable<RFn, Tag&, int>::value, "");132 static_assert(!std::is_invocable<Fn, Tag&>::value, "");133 static_assert(!std::is_invocable<Fn, Tag const&, int>::value, "");134 }135 {136 // Bullet 2137 using T = std::reference_wrapper<Tag>;138 using DT = std::reference_wrapper<DerFromTag>;139 using CT = std::reference_wrapper<const Tag>;140 static_assert(std::is_invocable<Fn, T&, int>::value, "");141 static_assert(std::is_invocable<Fn, DT&, int>::value, "");142 static_assert(std::is_invocable<Fn, const T&, int>::value, "");143 static_assert(std::is_invocable<Fn, T&&, int>::value, "");144 static_assert(!std::is_invocable<Fn, CT&, int>::value, "");145 static_assert(!std::is_invocable<RFn, T, int>::value, "");146 }147 {148 // Bullet 3149 using T = Tag*;150 using DT = DerFromTag*;151 using CT = const Tag*;152 using ST = std::unique_ptr<Tag>;153 static_assert(std::is_invocable<Fn, T&, int>::value, "");154 static_assert(std::is_invocable<Fn, DT&, int>::value, "");155 static_assert(std::is_invocable<Fn, const T&, int>::value, "");156 static_assert(std::is_invocable<Fn, T&&, int>::value, "");157 static_assert(std::is_invocable<Fn, ST, int>::value, "");158 static_assert(!std::is_invocable<Fn, CT&, int>::value, "");159 static_assert(!std::is_invocable<RFn, T, int>::value, "");160 }161 }162 {163 // Bullets 4, 5 and 6164 using Fn = int(Tag::*);165 static_assert(!std::is_invocable<Fn>::value, "");166 {167 // Bullet 4168 static_assert(std::is_invocable<Fn, Tag&>::value, "");169 static_assert(std::is_invocable<Fn, DerFromTag&>::value, "");170 static_assert(std::is_invocable<Fn, Tag&&>::value, "");171 static_assert(std::is_invocable<Fn, Tag const&>::value, "");172 }173 {174 // Bullet 5175 using T = std::reference_wrapper<Tag>;176 using DT = std::reference_wrapper<DerFromTag>;177 using CT = std::reference_wrapper<const Tag>;178 static_assert(std::is_invocable<Fn, T&>::value, "");179 static_assert(std::is_invocable<Fn, DT&>::value, "");180 static_assert(std::is_invocable<Fn, const T&>::value, "");181 static_assert(std::is_invocable<Fn, T&&>::value, "");182 static_assert(std::is_invocable<Fn, CT&>::value, "");183 }184 {185 // Bullet 6186 using T = Tag*;187 using DT = DerFromTag*;188 using CT = const Tag*;189 using ST = std::unique_ptr<Tag>;190 static_assert(std::is_invocable<Fn, T&>::value, "");191 static_assert(std::is_invocable<Fn, DT&>::value, "");192 static_assert(std::is_invocable<Fn, const T&>::value, "");193 static_assert(std::is_invocable<Fn, T&&>::value, "");194 static_assert(std::is_invocable<Fn, ST>::value, "");195 static_assert(std::is_invocable<Fn, CT&>::value, "");196 }197 }198 { // INVOKE bullet 7199 {// Function pointer200 using Fp = void(*)(Tag&, int);201 static_assert(std::is_invocable<Fp, Tag&, int>::value, "");202 static_assert(std::is_invocable<Fp, DerFromTag&, int>::value, "");203 static_assert(!std::is_invocable<Fp, const Tag&, int>::value, "");204 static_assert(!std::is_invocable<Fp>::value, "");205 static_assert(!std::is_invocable<Fp, Tag&>::value, "");206}207{208 // Function reference209 using Fp = void (&)(Tag&, int);210 static_assert(std::is_invocable<Fp, Tag&, int>::value, "");211 static_assert(std::is_invocable<Fp, DerFromTag&, int>::value, "");212 static_assert(!std::is_invocable<Fp, const Tag&, int>::value, "");213 static_assert(!std::is_invocable<Fp>::value, "");214 static_assert(!std::is_invocable<Fp, Tag&>::value, "");215}216{217 // Function object218 using Fn = NotCallableWithInt;219 static_assert(std::is_invocable<Fn, Tag>::value, "");220 static_assert(!std::is_invocable<Fn, int>::value, "");221}222}223{224 // Check that the conversion to the return type is properly checked225 using Fn = int (*)();226 static_assert(std::is_invocable_r<Implicit, Fn>::value, "");227 static_assert(std::is_invocable_r<double, Fn>::value, "");228 static_assert(std::is_invocable_r<const volatile void, Fn>::value, "");229 static_assert(!std::is_invocable_r<Explicit, Fn>::value, "");230}231{232 // Check for is_invocable_v233 using Fn = void (*)();234 static_assert(std::is_invocable_v<Fn>, "");235 static_assert(!std::is_invocable_v<Fn, int>, "");236}237{238 // Check for is_invocable_r_v239 using Fn = void (*)();240 static_assert(std::is_invocable_r_v<void, Fn>, "");241 static_assert(!std::is_invocable_r_v<int, Fn>, "");242}243 return 0;244}245