// Copyright (c) OpenMMLab. All rights reserved. #ifndef MMDEPLOY_SRC_EXPERIMENTAL_COLLECTION_H_ #define MMDEPLOY_SRC_EXPERIMENTAL_COLLECTION_H_ #include "token.h" namespace mmdeploy { class Collection { public: template friend Collection& operator<<(Collection& c, const Token& value) { c.put(value); return c; } template friend const Collection& operator>>(const Collection& c, Token& value) { c.get(value); return c; } template Result maybe() const { T token; if (get(token)) { return token; } return Status(eFail); } private: std::vector keys_; std::vector> values_; template void put(const Token& value) { keys_.push_back(Token::key()); values_.push_back(std::make_shared>(value)); } template bool get(Token& value) const { for (int i = 0; i < keys_.size(); ++i) { if (keys_[i] == Token::key()) { value = *static_cast*>(values_[i].get()); return true; } } return false; } }; namespace detail { template struct function_traits { template static std::tuple get_args(std::function); template static R get_ret(std::function); using args_t = decltype(get_args(std::function{std::declval()})); using ret_t = decltype(get_ret(std::function{std::declval()})); }; // TODO: obtain first error // TODO: combine all errors template > Result Apply(F&& f, const Result&... args) { if ((... && args)) { return std::invoke(std::forward(f), args.value()...); } return Status(eFail); } template > Result ApplyImpl(F&& f, const Collection& c, std::tuple*) { return Apply(std::forward(f), c.maybe()...); } } // namespace detail template ::args_t> decltype(auto) Apply(F&& f, const Collection& c) { return detail::ApplyImpl(std::forward(f), c, std::add_pointer_t{}); } } // namespace mmdeploy #endif // MMDEPLOY_SRC_EXPERIMENTAL_COLLECTION_H_