Восстановление указателя на функцию из boost :: any - PullRequest
0 голосов
/ 24 октября 2011

Я хочу использовать boost :: any для хранения разнородных указателей функций. Я получаю исключение, когда пытаюсь использовать boost :: any_cast для повторного указания на указатель функции.

То, что я хочу сделать, даже разрешено?

.h:

typedef void(*voidFunction)(void);
struct functionInfo{
       CString    functionName;
       boost::any functionPointer;
};
void foo();
int foo2(int a);

.cpp

void foo()
{
  ;//do something
}

int foo2(int a)
{
  ;//do something
}

void main()
{
    vector<functionInfo> functionList;
    functionInfo myInfo;
    myInfo.functionName = _T("foo");
    myInfo.functionPointer = &foo;
    functionList.push_back(myInfo);
    myInfo.functionName = _T("foo2");
    myInfo.functionPointer = &foo2;
    functionList.push_back(myInfo);

    voidFunction myVoidFunction = boost::any_cast<voidFunction>(functionList[0].functionPointer);

}

---- EDIT ----

Хорошо, вы правы, причина, по которой он так поступил, в том, что foo является функцией-членом класса.

Значение:

void MyClass::foo();

myInfo.functionPointer = &MyClass::foo;

поэтому мне нужно было набратьdef:

typedef void(MyClass::*voidClassFunction)(void);
voidClassFunction myVoidFunction = boost::any_cast<voidClassFunction>(functionList[0].functionPointer);

1 Ответ

1 голос
/ 24 октября 2011

То, что я хочу сделать, даже разрешено?

Абсолютно.Пока вы приводите его обратно к точно типу, который вы ему дали.

И это ваша проблема.Вы неfoo2 не является voidFunction.Следовательно, вы не можете привести его к единице.

Цель boost::any состоит в том, чтобы иметь void*, который гарантированно либо работает правильно в соответствии со стандартом C ++, либо выдает исключение.Стандарт C ++ позволяет преобразовывать любой (не являющийся членом) тип указателя в void*.Это также позволяет преобразовывать void* обратно в тип при условии, что предоставляемый тип точно такого же типа , что и оригинал.Если это не так, добро пожаловать в неопределенное поведение.

boost::any существует, чтобы предотвратить неопределенное поведение, сохраняя информацию о типе с void*.Это правильно сгенерирует исключение, когда вы попытаетесь привести что-то к неправильному типу.Как вы делаете здесь.boost::any - это , а не способ притвориться, что типы не существуют, и притвориться, что вы можете превратить что-либо во что-то другое.Это просто типобезопасный контейнер без типа.Вам все еще нужно знать, что вы на самом деле поместили туда.

Невозможно сохранить список функций с произвольными списками аргументов и вызывать их с тем же списком аргументов.Пользователь должен предоставить функции или функтору правильный список аргументов, который вы ожидаете.boost::bind - это способ адаптации функции / функтора для определенного списка аргументов, но пользователь должен явно использовать его.

Лучшее, что вы можете сделать, - это иметь список определенных наборов параметров функции, которые вы принимаете,хранится в объекте boost::variant.Вы можете использовать посетителя, чтобы выяснить, какую функцию вызывать.

...