Функции / функторы как параметры шаблона. Могут ли они храниться? - PullRequest
7 голосов
/ 02 марта 2012

Представьте, что у меня есть следующие бесплатные функции и функтор:

void myFreeFunction(void)
{
    cout << "Executing free function" << endl;
}

struct MyFunctor
{
    void operator()(void)
    {
        cout << "Executing functor" << endl;
    }
};

Как указано в этом ответе , я могу передать свою функцию или функтор в качестве аргумента шаблона другой функции:

template <typename F>
void doOperation(F f)
{
    f();
}

А затем позвоните:

doOperation(myFreeFunction);
doOperation(MyFunctor());

Пока все хорошо. Но что, если я хочу что-то вроде следующего:

template<typename Callback>
class MyClass
{
private:
    Callback mCallback;

public:
    MyClass(){}

    void execute()
    {
        mCallback();
    }
};

В этом случае я указываю функцию / функтор, когда объявляю класс, но не вызываю его до тех пор, пока не позже. Работает для функторов:

MyClass<MyFunctor> myClass1;
myClass1.execute();

Но не для функций:

MyClass<myFreeFunction> myClass2;
myClass2.execute();

Компилятор говорит:

ошибка C2923: «MyClass»: «myFreeFunction» не является допустимым аргументом типа шаблона для параметра «Callback»

Что достаточно справедливо ... но как бы вы это структурировали?

Примечание: Я знаю о std :: function и могу использовать это. Хотя это заметно медленнее, поэтому я смотрю на все варианты.

Спасибо

David

1 Ответ

7 голосов
/ 02 марта 2012

Проблема в том, что freefunction - это не тип, а элемент of (в данном случае указатель на функцию.

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

myclass<call_back_t> my_class(call_back);

РЕДАКТИРОВАТЬ: В C ++ 11 тип можно получить от decltype(call_back)

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

//this should be in the namespace of the class or a static member of it
template<FuncType>
myclass<FuncType> make_class(FuncType func)
{
     return myclass<FuncType>(func);
}
//called like
myclass mc=make_class(&my_callback);

Не пытайтесь изменить конструктор

template<typename CallBack>
myclass{
private:
   CallBack call_back;
public:
   myclass(CallBack call_back_)
   : call_back(call_back_)
   {}
};

или что-то в этом роде

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...