C ++ 0x: ошибка с аргументами std :: function :: target и template - PullRequest
4 голосов
/ 19 июня 2011

Я сейчас пишу в системе обработчиков событий на C ++ 0x. «Обработчики» для каждого события (может быть несколько обработчиков) регистрируются путем передачи любого вида функции / метода, которые могут быть сохранены в объекте std::function. Это делается в стиле C # с использованием перегруженного оператора + =. Мой Event-Class выглядит в основном так (раздет для лучшей читаемости):

template<typename THandlerReturn, typename THandlerArgs...>
class Event {
    public:
        typedef THandlerReturn(HandlerSignature)(THandlerArgs...);
        typedef THandlerReturn(*HandlerFuntionPtr)(THandlerArgs...);
        typedef typename std::function<HandlerSignature> HandlerFunction;

        void operator += (HandlerFunction handler) {
            _handlers.push_back(handler);
        }

        // Some other methods for calling all handlers, ctors, etc.

    private:
        std::vector<HandlerFunction> _handlers;
};

Теперь у меня есть другой внутренний метод для извлечения фактического указателя на функцию из std::function объектов, хранящихся в векторе. В основном он пытается сделать что-то вроде этого:

// Preceeding: Get an iterator 'it' from the vector
HandlerFunctionPtr pt2func = it->target<HandlerSignature>();

В этот момент, когда я использую класс Event в своем приложении, компиляция завершится неудачно. Используя сборку GCC 4.7, я получаю следующие сообщения об ошибках для строки выше:

error: expected primary-expression before '>' token
error: expected primary-expression before ')' token

Я немного протестировал метод target<>(), и следующее прекрасно работает, предполагая, что тип возвращаемого значения void и есть один аргумент типа int:

typedef void(Signature)(int);
typedef void(*FunctionPtr)(int);
std::function<Signature> func;
FunctionPtr pt2func = func.target<Signature>();

Но как только включается один аргумент шаблона, я получаю опубликованные выше ошибки:

typedef THandlerReturn(Signature)(int);
typedef THandlerReturn(*FunctionPtr)(void);
std::function<Signature> func;
FunctionPtr pt2func = func.target<Signature>();

Может кто-нибудь сказать мне, почему это на самом деле, и если да, есть ли способ заставить это работать? Любая помощь и идеи очень ценятся! Заранее спасибо!

1 Ответ

5 голосов
/ 19 июня 2011

Вам необходимо использовать ключевое слово template как:

HandlerFunctionPtr pt2func = it->template target<HandlerSignature>();

Это потому, что вы вызываете шаблон функции для объекта, тип которого зависит от аргумента шаблона.При отсутствии ключевого слова template компилятор будет анализировать ваш код как

HandlerFunctionPtr pt2func = ( (it->target) < HandlerSignature ) >();

, что абсолютно бессмысленно.Отсюда и ошибка.


Чтобы узнать это подробно о том, зачем нужен template, прочитайте это превосходное объяснение @ Johannes Schaub :

...