1 | #pragma once |
2 | |
3 | #include <typeindex> |
4 | #include <c10/core/DispatchKeySet.h> |
5 | #include <c10/macros/Macros.h> |
6 | #include <c10/util/Metaprogramming.h> |
7 | #include <c10/util/Type.h> |
8 | |
9 | namespace c10 { |
10 | namespace impl { |
11 | |
12 | // A CppSignature object holds RTTI information about a C++ function signature at runtime |
13 | // and can compare them or get a debug-printable name. |
14 | class TORCH_API CppSignature final { |
15 | public: |
16 | CppSignature(const CppSignature&) = default; |
17 | CppSignature(CppSignature&&) noexcept = default; |
18 | CppSignature& operator=(const CppSignature&) = default; |
19 | CppSignature& operator=(CppSignature&&) noexcept = default; |
20 | |
21 | template<class FuncType> |
22 | static CppSignature make() { |
23 | // Normalize functors, lambdas, function pointers, etc. into the plain function type |
24 | // The first argument of the schema might be of type DispatchKeySet, in which case we remove it. |
25 | // We do this to guarantee that all CppSignature's for an operator will match, even if they're registered |
26 | // with different calling conventions. |
27 | // See Note [Plumbing Keys Through The Dispatcher] |
28 | using decayed_function_type = typename c10::remove_DispatchKeySet_arg_from_func<std::decay_t<FuncType>>::func_type; |
29 | |
30 | return CppSignature(std::type_index(typeid(decayed_function_type))); |
31 | } |
32 | |
33 | std::string name() const { |
34 | return c10::demangle(signature_.name()); |
35 | } |
36 | |
37 | friend bool operator==(const CppSignature& lhs, const CppSignature& rhs) { |
38 | if (lhs.signature_ == rhs.signature_) { |
39 | return true; |
40 | } |
41 | // Without RTLD_GLOBAL, the type_index comparison could yield false because |
42 | // they point to different instances of the RTTI data, but the types would |
43 | // still be the same. Let's check for that case too. |
44 | // Note that there still is a case where this might not work, i.e. when |
45 | // linking libraries of different compilers together, they might have |
46 | // different ways to serialize a type name. That, together with a missing |
47 | // RTLD_GLOBAL, would still fail this. |
48 | if (0 == strcmp(lhs.signature_.name(), rhs.signature_.name())) { |
49 | return true; |
50 | } |
51 | |
52 | return false; |
53 | } |
54 | |
55 | private: |
56 | explicit CppSignature(std::type_index signature): signature_(std::move(signature)) {} |
57 | std::type_index signature_; |
58 | }; |
59 | |
60 | inline bool operator!=(const CppSignature& lhs, const CppSignature& rhs) { |
61 | return !(lhs == rhs ); |
62 | } |
63 | |
64 | } |
65 | } |
66 | |