/** This file is a part of rexy's general purpose library Copyright (C) 2022 rexy712 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 3 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, see . */ #ifndef REXY_UTIL_DEFERRED_HPP #define REXY_UTIL_DEFERRED_HPP #include #include //forward, index_sequence #include //size_t #include "compat/standard.hpp" namespace rexy{ template class deferred { public: using value_type = T; private: std::tuple m_args; public: template constexpr deferred(FArgs&&... args); REXY_CPP20_CONSTEXPR deferred(const deferred&) = default; REXY_CPP20_CONSTEXPR deferred(deferred&&) = default; REXY_CPP20_CONSTEXPR ~deferred(void) = default; REXY_CPP20_CONSTEXPR deferred& operator=(const deferred&) = default; REXY_CPP20_CONSTEXPR deferred& operator=(deferred&&) = default; constexpr value_type value(void); constexpr operator value_type(void); private: template constexpr value_type get_value_(std::index_sequence); }; template class deferred_function { public: using ret_t = decltype(std::declval()(std::declval()...)); private: Fn m_fn; std::tuple m_args; public: template constexpr deferred_function(F&& f, FArgs&&... args); constexpr decltype(auto) operator()(void); constexpr decltype(auto) value(void); constexpr operator ret_t(void); private: template constexpr decltype(auto) get_value_(std::index_sequence); }; template template constexpr deferred::deferred(FArgs&&... args): m_args{std::forward(args)...}{} template constexpr auto deferred::value(void) -> value_type{ return get_value_(std::make_index_sequence()); } template constexpr deferred::operator value_type(void){ return get_value_(std::make_index_sequence()); } template template constexpr auto deferred::get_value_(std::index_sequence) -> value_type{ return T{std::forward>(std::get(m_args))...}; } template template constexpr deferred_function::deferred_function(F&& f, FArgs&&... args): m_fn(std::forward(f)), m_args{std::forward(args)...}{} template constexpr decltype(auto) deferred_function::operator()(void){ return get_value_(std::make_index_sequence()); } template constexpr decltype(auto) deferred_function::value(void){ return get_value_(std::make_index_sequence()); } template constexpr deferred_function::operator ret_t(void){ return get_value_(std::make_index_sequence()); } template template constexpr decltype(auto) deferred_function::get_value_(std::index_sequence){ return std::forward(m_fn)(std::forward>(std::get(m_args))...); } template deferred_function(Fn&&, Args&&...) -> deferred_function; template deferred make_deferred(Args&&... args){ return deferred(std::forward(args)...); } } #endif