/****************************************************************************** * Icinga 2 * * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * * as published by the Free Software Foundation; either version 2 * * of the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software Foundation * * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ******************************************************************************/ #ifndef FUNCTIONWRAPPER_H #define FUNCTIONWRAPPER_H #include "base/i2-base.hpp" #include "base/value.hpp" #include #include #include using namespace std::placeholders; namespace icinga { inline std::function&)> WrapFunction(const std::function&)>& function) { return function; } inline std::function&)> WrapFunction(void (*function)(const std::vector&)) { return [function](const std::vector& arguments) { function(arguments); return Empty; }; } template std::function&)> WrapFunction(Return (*function)(const std::vector&)) { return [function](const std::vector& arguments) { return static_cast(function(arguments)); }; } template struct indices { using next = indices; }; template struct build_indices { using type = typename build_indices::type::next; }; template <> struct build_indices<0> { using type = indices<>; }; template using BuildIndices = typename build_indices::type; struct unpack_caller { private: template auto call(FuncType f, const std::vector& args, indices) -> decltype(f(args[I]...)) { return f(args[I]...); } public: template auto operator () (FuncType f, const std::vector& args) -> decltype(call(f, args, BuildIndices::type>::value>{})) { return call(f, args, BuildIndices::type>::value>{}); } }; enum class enabler_t {}; template using EnableIf = typename std::enable_if::type; template std::function&)> WrapFunction(FuncType function, EnableIf())), void>::value>* = 0) { return [function](const std::vector& arguments) { constexpr int arity = boost::function_types::function_arity::type>::value; if (arguments.size() < arity) BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); else if (arguments.size() > arity) BOOST_THROW_EXCEPTION(std::invalid_argument("Too many arguments for function.")); unpack_caller()(function, arguments); return Empty; }; } template std::function&)> WrapFunction(FuncType function, EnableIf())), void>::value>* = 0) { return [function](const std::vector& arguments) { constexpr int arity = boost::function_types::function_arity::type>::value; if (arity > 0) { if (arguments.size() < arity) BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function.")); else if (arguments.size() > arity) BOOST_THROW_EXCEPTION(std::invalid_argument("Too many arguments for function.")); } return unpack_caller()(function, arguments); }; } } #endif /* FUNCTIONWRAPPER_H */