/** * 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_VERIFIER_UTIL_FUNCTION_TRAITS_ #define PANDA_VERIFIER_UTIL_FUNCTION_TRAITS_ #include namespace panda::verifier { template struct indices { }; template struct gen_indices : gen_indices { }; template struct gen_indices<0, S...> { typedef indices type; }; template struct function_signature_helper; template struct function_signature_helper : public function_signature_helper { }; template struct function_signature_helper : public function_signature_helper { }; template struct function_signature_helper : public function_signature_helper { }; template struct function_signature_helper { using return_type = R; using args_tuple = std::tuple; static constexpr std::size_t arity = sizeof...(Args); template struct argument { static_assert(N < arity, "invalid argument index"); using type = std::tuple_element_t; }; template using arg_type = typename argument::type; }; template class function_signature : public function_signature_helper { using base = function_signature_helper; public: template static typename base::return_type call(L f, std::tuple &&args) { return call_helper(f, std::forward(args), typename gen_indices::type {}); } private: template static typename base::return_type call_helper(L f, A &&a, indices) { return f(std::forward(std::get(a))...); } }; template class n_ary { public: using sig = function_signature; using ret_type = std::decay_t; using lhs_type = std::decay_t::type>; using rhs_type = std::decay_t::type>; static_assert(sig::arity == 0x2, "only binary operation is expected"); static_assert(std::is_same::value, "argument types should be the same"); static_assert(std::is_same::value, "return value type should be the same as arguments one"); using type = ret_type; n_ary(BinOp op) : binop {op} {} auto operator()(type lhs, type rhs) { return binop(lhs, rhs); } template auto operator()(type lhs, Args &&... args) { return binop(lhs, operator()(std::forward(args)...)); } template auto operator()(std::tuple &&args) { return call_helper(std::forward>(args), typename gen_indices::type {}); } private: template auto call_helper(A &&a, indices) { return operator()(std::forward>(std::get(a))...); } BinOp binop; }; } // namespace panda::verifier #endif // !PANDA_VERIFIER_UTIL_FUNCTION_TRAITS_