Не очень понимаю, как на модных плюсиках сделать такую шляпу
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 21.09.23 12:47
Оценка:
Здравствуйте!

Есть интерфейс, с какими-то виртуальными методами. Есть какие-то реализации этого интерфейса.

Есть отдельная реализация, которая хранит в себе указатели на несколько реализаций того же интерфейса, и каждый вызов метода через эту мульти реализацию должен вызывать этот метод через все хранящиеся указатели на другие реализации.

При этом, если метод что-то возвращает, то за результат берём вызов через первый хранящийся указатель на интерфейс, а остальное игнорируем

  Как-то так
#pragma once

#include <iostream>
#include <memory>


struct IDelegationTest
{

    virtual bool getter() = 0;
    virtual bool setter(bool b) = 0;
    virtual void jobImpl(bool b, int i) = 0;
    virtual void jobImpl(bool b, int i, std::string s) = 0; // !!! А что будет с этой перегрузкой?
    virtual int jobImpl2(bool b, int i) = 0;

};


struct DelegationTestImpl : public IDelegationTest
{
    int n = 0;

    virtual bool getter() override
    {
        std::cout << "DelegationTestImpl::getter(), n: " << n << "\n";
        return true;
    }

    virtual bool setter(bool b) override
    {
        std::cout << "DelegationTestImpl::setter(bool b), b: " << b << ", n: " << n << "\n";
        return true;
    }

    virtual void jobImpl(bool b, int i) override
    {
        std::cout << "DelegationTestImpl::jobImpl(bool b, int i), b: " << b << ", i: " << i << ", n: " << n << "\n";
    }

    virtual int jobImpl2(bool b, int i) override
    {
        std::cout << "DelegationTestImpl::jobImpl2(bool b, int i), b: " << b << ", i: " << i << ", n: " << n << "\n";
        return n;
    }

};


struct DelegatorImpl : public IDelegationTest
{
    std::vector< std::shared_ptr<IDelegationTest> > impls;

    template <typename Return, typename... Args>
    Return delegateCall( Return(IDelegationTest::*func)(Args...), Args...)
    {
        // !!! Тут assert на тему impls не должен быть пустым

        std::vector<std::shared_ptr>::const_iterator it = impls.begin();

        // !!! Или assert тут по it!=impls.end();

        // Получаем результат
        auto res = it->func(Args...); ++it;

        for(; it!=impls.end(); ++it)
        {
            // Вызываем метод для всех экземпляров имплементаций
            it->func(Args...); ++it;
        }

        return res;
    }

    // 
    template <typename... Args>
    void delegateCall( void(IDelegationTest::*func)(Args...), Args...)
    {
        std::vector<std::shared_ptr>::const_iterator it = impls.begin();
        for(; it!=impls.end(); ++it)
        {
            // Вызываем метод для всех экземпляров имплементаций
            it->func(Args...); ++it;
        }
    }

    // !!! Тут ещё проблема, а что будет с перегруженными виртуальными методами?


    virtual bool getter() override
    {
        return delegateCall(getter);
    }

    virtual bool setter(bool b)
    {
        return delegateCall(setter, b);
    }

    virtual void jobImpl(bool b, int i)
    {
        delegateCall(jobImpl, b, i);
    }

    virtual void jobImpl2(bool b, int i)
    {
        return delegateCall(jobImpl2, b, i);
    }

};


inline
std::shared_ptr<IDelegationTest> makeDelegator()
{
    DelegatorImpl impl;

    impl.impls.emplace_back(std::make_shared<DelegationTestImpl>(1));
    impl.impls.emplace_back(std::make_shared<DelegationTestImpl>(2));

    // !!! Тут надо создать экземпляр DelegatorImpl, но вернуть надо std::make_shared<IDelegationTest>
    return std::make_shared<IDelegationTest>(impl);
}


int main()
{
    std::shared_ptr<IDelegationTest> pDelegator = makeDelegator();

    pDelegator->getter();
    pDelegator->setter(true);
    pDelegator->jobImpl(false, 3);
    pDelegator->jobImpl2(true, 5);
}
Маньяк Робокряк колесит по городу
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.