#c #boost #function-pointers #boost-any
#c #boost #указатели на функции #boost-любой
Вопрос:
Я хочу использовать 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 = amp;foo;
functionList.push_back(myInfo);
myInfo.functionName = _T("foo2");
myInfo.functionPointer = amp;foo2;
functionList.push_back(myInfo);
voidFunction myVoidFunction = boost::any_cast<voidFunction>(functionList[0].functionPointer);
}
—-РЕДАКТИРОВАТЬ—-
Хорошо, вы правы, причина, по которой он действовал так, заключается в том, что foo является функцией-членом класса.
Значение:
void MyClass::foo();
myInfo.functionPointer = amp;MyClass::foo;
итак, мне нужно было ввести typedef:
typedef void(MyClass::*voidClassFunction)(void);
voidClassFunction myVoidFunction = boost::any_cast<voidClassFunction>(functionList[0].functionPointer);
Комментарии:
1. Если я изменю код на фактическую компиляцию (избавлюсь от CString/_T cruft и добавлю правильные включения), у меня все работает нормально. Конечно, если вы попытаетесь привести
functionList[1].functionPointer
к avoidFunction
, вы получите ожидаемое исключение.
Ответ №1:
Разрешено ли то, что я хочу сделать?
Абсолютно. При условии, что вы приведете его обратно к тому типу, который вы ему дали.
И это ваша проблема. Вы этого не делаете. foo2
это не а voidFunction
. Поэтому вы не можете привести его к единице.
Цель boost::any
состоит в том, чтобы иметь a void*
, который гарантированно либо будет корректно работать в соответствии со стандартом C , либо выдаст исключение. Стандарт C допускает преобразование любого (не являющегося членом) типа указателя в a void*
. Это также позволяет преобразовать void*
обратный тип в тип, при условии, что предоставляемый тип в точности совпадает с исходным. Если это не так, добро пожаловать в неопределенное поведение.
boost::any
существует для предотвращения неопределенного поведения путем сохранения информации о типе с void*
помощью . Он будет правильно генерировать исключение, когда вы попытаетесь привести что-либо к неправильному типу. Как вы делаете здесь. boost::any
это не способ притворяться, что типов не существует, и притворяться, что вы можете превратить что угодно во что-то другое. Это просто типобезопасный контейнер без типов. Вам все равно нужно знать, что вы на самом деле туда кладете.
Невозможно сохранить список функций с произвольными списками аргументов и вызывать их с тем же списком аргументов. Пользователь должен предоставить функции или функтору правильный список аргументов, который вы ожидаете. boost::bind
это способ адаптировать функцию / функтор для определенного списка аргументов, но пользователь должен явно использовать его.
Лучшее, что вы можете сделать, это иметь список конкретных наборов параметров функции, которые вы принимаете, хранящихся в boost::variant
объекте. Вы можете использовать посетителя, чтобы выяснить, какую конкретную функцию вызывать.
Комментарии:
1. не беспокойтесь, я бы не стал пытаться преобразовать foo2 в «voidFunction», источник моей ошибки см. В Моей правке, но спасибо за оставшуюся информацию, я изучу ее.