Определить контекст внутри функции-члена, вызываемой указателем на нее - PullRequest
1 голос
/ 10 апреля 2019

Название может быть недостаточно пояснительным, поскольку проблему трудно описать.

У меня есть следующие (упрощенные) две структуры данных в библиотеке, которые я не могу изменить:

class A;

typedef void(A::*AMemFunc)();
struct FooBar
{
    AMemFunc func;
    std::string identifier;
};

class A
{
    private:
        std::vector<FooBar *> theCollection;

    public:
        virtual ~A()
        {
            for (auto fooBar : theCollection)
            {
                delete fooBar;
            }

            theCollection.clear();
        }

        void AddToCollection(AMemFunc func, const std::string &identifier)
        {
            FooBar *newFooBar = new FooBar();
            newFooBar->func = func;
            newFooBar->identifier = identifier;

            theCollection.push_back(newFooBar);
        }

        void RemoveFromCollection(const std::string &identifier)
        {
            for (auto collectionIt = theCollection.begin(); collectionIt != theCollection.end(); collectionIt++)
            {
                FooBar *currentFooBar = *collectionIt;
                if (currentFooBar->identifier == identifier)
                {
                    collectionIt = theCollection.erase(collectionIt);
                    delete currentFooBar;
                    currentFooBar = nullptr;
                }
            }
        }

        const std::vector<FooBar *> &getTheCollection() const
        {
            return theCollection;
        }
};

Функция-член вызывается из библиотеки и находится вне моего контроля. Теперь пользователь библиотеки может создавать подклассы A и добавлять функцию-член в коллекцию следующим образом:

class B : public A
{
    public:
        B()
        {
            AddToCollection((AMemFunc)&B::Test, "MyIdentifier");
        }

        void Test()
        {

        }
};

Теперь я хочу создать оболочку C ++ / CLI для этой функции (наследование от A и возможность назначать метод-член). Подробности создания экземпляра B для простоты опущены:

ref class WrapperB
{
    public:
        delegate void AMemFuncDelegate();

        void AddToCollection(AMemFuncDelegate ^func, String ^identifier)
        {
            // Do stuff
        }
};

Но передо мной стоит проблема, как я мог бы разрешить динамическое создание указателей на функции-члены.

Это решения, которые я до сих пор предлагал:

  • вообще игнорировать неуправляемый std :: vector и полностью управлять им в c ++ / cli (подробности опущены, но это возможно). Недостатком является то, что сторона C ++ не имеет возможностей взаимодействия (или знаний о) с управляемыми функциями.
  • Определить N функций-членов в B, которые передают уникальный идентификатор управляемой стороне, которая может быть связана с делегатом. Это ограничивает количество вещей, которые вы можете добавить в коллекцию, и дает много беспорядка кода и дублирования. Также, когда пользователь вызывает RemoveFromCollection, я не могу обнаружить удаление FooBar (без виртуального деструктора) и отделить управляемый делегат. Но это действительно проблема во всех ситуациях

Оба решения, которые я придумала до сих пор, не идеальны, и я не уверен, что что-то здесь упущено.

Редактировать: я не могу использовать c ++ 11 или выше на неуправляемой стороне.

...