/** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef PANDA_VERIF_PARSER_CALLABLE_H_ #define PANDA_VERIF_PARSER_CALLABLE_H_ #include #include namespace panda::verifier { /* this is lightweight analogue of std::function. Type-erased holder of function, closure or object with operator(). NB! it does not keep object contents, only pointers, so a closure must be accessible during lifetime of the callable<...> object. Motivation: in many cases using type-erased callable object based on std::function is very heavy-weight: extra allocations, data copying, vtbls and so on. So here is lightweight counterpart, using static type-erasing without extra storage other than two explicit private pointers. */ template class callable; template class callable { struct callable_type { R operator()(Args...); }; typedef R (callable_type::*method_type)(Args...); typedef R (*function_type)(Args...); callable_type *object {nullptr}; union method_union { method_type m; function_type f; method_union(method_type method) : m(method) {} method_union(function_type function) : f(function) {} method_union() : m {nullptr} {} ~method_union() = default; } method; public: using Result = R; using Arguments = std::tuple; callable() = default; callable(const callable &) = default; callable(callable &&) = default; callable &operator=(const callable &) = default; callable &operator=(callable &&) = default; ~callable() = default; template (&T::operator()))> constexpr callable(const T &obj) : object {reinterpret_cast(&const_cast(obj))}, method {reinterpret_cast(static_cast(&T::operator()))} { } template (&T::operator()))> constexpr callable(T &obj) : object {reinterpret_cast(&const_cast(obj))}, method {reinterpret_cast(static_cast(&T::operator()))} { } template constexpr callable(const T &obj, R (T::*param_method)(Args...) const) : object {reinterpret_cast(&const_cast(obj))}, method {reinterpret_cast(param_method)} { } template constexpr callable(T &obj, R (T::*param_method)(Args...)) : object {reinterpret_cast(&const_cast(obj))}, method {reinterpret_cast(param_method)} { } constexpr callable(function_type func) : object {nullptr}, method {func} {} constexpr R operator()(Args... args) const { if (object == nullptr) { return (method.f)(args...); } return (object->*(method.m))(args...); } operator bool() const { return (method.m != nullptr) || (method.f != nullptr); } }; } // namespace panda::verifier #endif // PANDA_VERIF_PARSER_CALLABLE_H_