Восстановление указателя на функцию из boost::any

#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 к a voidFunction , вы получите ожидаемое исключение.

Ответ №1:

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

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

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

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

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

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

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

Комментарии:

1. не беспокойтесь, я бы не стал пытаться преобразовать foo2 в «voidFunction», источник моей ошибки см. В Моей правке, но спасибо за оставшуюся информацию, я изучу ее.