Можно ли определить тип поля класса, исходя из типа объекта, возвращаемого функцией используемой в этом классе?

Очень странная потребность, но я постараюсь объяснить чем она вызвана на примере кода ниже. Я использую библиотеку для работы с pg под названием ozo, она базируется на boost::asio. Для того чтоб выполнить запрос, в функтор нужно передать collback c двумя аргументами, первый - код ошибки, второй - коннекшен. Вот это место в представленном ниже коде

 reqOp.reqOp(std::move(provider), std::move(query), t, out, [this, coro](ozo::error_code ec,
                                                                                    auto conn) mutable {
                this->ec = ec;
                this->conn = conn;
                coro.resume();
            });

Тип коннекшена определяется на этапе компиляции исходя из многих факторов, все из передаваемого провайдера(первый аргумент функтора). До алгоритма определения в исходниках я докопаться не смог. Я пытаюсь написать обертку, позволяющую использовать эту библиотеку с корутинами с++20. Для этого я создаю класс Awaiter, в полях которого я хочу сохранять переданные в callback ошибку и конекшен. Проблема состоит в определении типа поля коннекшена в классе Awaiter. В примере ниже я использую тип

using ConnectionPtr = std::shared_ptr<ozo::pooled_connection<
        yamail::resource_pool::handle<ozo::connection_rep<ozo::oid_map_t<>,
                ozo::none_t>>, boost::asio::io_context::executor_type>>;\

Что неправильно, потому что данные тип подходит только для одного конкретного случая. Каким образом, исходя из типа, определяемого на этапе компиляции для второго аргумента колбека (ozo::error_code ec,auto conn) можно определить тип поля коннекшена в классе Awaiter. И возможно ли это сделать вообще. Необходимость сохранять конекшен в классе Awaiter возникла потому, что другого способа вернуть его через resume корутины, как известно мне, не предполагают. Как можно решить данную пробелму?

using ConnectionPtr = std::shared_ptr<ozo::pooled_connection<
        yamail::resource_pool::handle<ozo::connection_rep<ozo::oid_map_t<>,
                ozo::none_t>>, boost::asio::io_context::executor_type>>;

template<typename Initiator>
class RequestOp {
private:
    ozo::request_op<Initiator> reqOp;
private:

    template<typename P, typename Q, typename TimeConstraint, typename Out>
    struct Awaiter {
        const RequestOp<Initiator> &reqOp;
        P &&provider;
        Q &&query;
        TimeConstraint t;
        Out out;

        ozo::error_code ec;
        ConnectionPtr conn;

        bool await_ready() {
            return false;
        }

        void await_suspend(std::coroutine_handle<> coro) {
            reqOp.reqOp(std::move(provider), std::move(query), t, out, [this, coro](ozo::error_code ec,
                                                                                    auto conn) mutable {
                this->ec = ec;
                this->conn = conn;
                coro.resume();
            });

        }

        decltype(auto) await_resume() {
            return std::pair<ConnectionPtr, ozo::error_code>{conn, ec};
        }
    };

public:
    template<typename P, typename Q, typename TimeConstraint, typename Out>
    decltype(auto) operator()(P &&provider, Q &&query, TimeConstraint t, Out out) const {
        return Awaiter<P, Q, TimeConstraint, Out>{*this, std::forward<P>(provider), std::forward<Q>(query), t, out};
    }
};

constexpr RequestOp<ozo::detail::initiate_async_request> Request;

Ответы (0 шт):