2012-01-10 2 views
0

Я пытаюсь реализовать версию-функтор static_cast для использования в std::bind().Функторная версия static_cast в std :: bind()

Я знаю Boost ll_static_cast<K>() (см. using static_cast with boost::bind), но я не использую Boost прямо сейчас.

Существует пример кода в Why do several of the standard operators not have standard functors?, но он не будет компилироваться GCC 4.2.1:

template <typename Target> 
struct StaticCast 
{ 
    template <typename Source> 
    Target operator()(Source&& source) const 
    { 
     return static_cast<Target>(source); 
    } 
} 

мне удалось получить что-то для компиляции, но я не уверен, что это правильно:

template <class Target> 
struct StaticCast : public std::unary_function<void, Target> { 
    template <class Source> 
    Target operator()(Source& src) const { 
     return static_cast<Target>(src); 
    } 
}; 

Может кто-нибудь сказать мне, если эта версия верна, и если это так, зачем мне std::unary_function, который не используется в предыдущем примере кода?

Использование:

std::vector<BaseObject*> vec; // BaseObject* are known to be of type 
    // DerivedObject* of course, please don't ask me how or why... 

std::for_each(vec.begin(), vec.end(), 
    std::bind(&DerivedObject::doStuff, 
     std::bind(StaticCast<DerivedObject*>(), std::placeholders::_1), 
    "with some string")); 
+0

Если вы используете C++ 11, но не использовать лямбды? 'std :: for_each (vec.begin(), vec.end(), [] (BaseObject * obj) {static_cast (obj) -> doStuff();}' – kennytm

+0

К сожалению, я застрял с GCC 4.2.1 на данный момент, который их не поддерживает (я просто удалил 'tr1 ::' в коде) – OlivierB

ответ

0

Учитывая отсутствие совершенного экспедирования в C++ 03, вы должны сделать из-за с перегрузками:

template<class Target> 
struct StaticCast 
{ 
    typedef Target result_type; 

    template<class Source> 
    Target operator()(Source& src) const 
    { 
     return static_cast<Target>(src); 
    } 

    template<class Source> 
    Target operator()(Source const& src) const 
    { 
     return static_cast<Target>(src); 
    } 
}; 

Примечание что я явно делаю typedef для result_type вместо того, чтобы наследовать от std::unary_function<>. Причина в том, что первым параметром шаблона до std::unary_function<> должен быть тип аргументов operator(), но поскольку наш operator() является шаблоном, мы не можем знать это заранее, поэтому неискренне предлагать его в первую очередь (особенно void, что подразумевает, что operator() является нулевым, когда на самом деле он унарный).саке


Кроме того, для полноты, вот правильная версия C++ 11 функтора:

template<class Target> 
struct StaticCast 
{ 
    template<class Source> 
    Target operator()(Source&& source) const 
    { 
     return static_cast<Target>(std::forward<Source>(source)); 
    } 
} 
0

Одна из причин, первая одна не работает, вероятно, потому, что вы используете RValue ссылки на компилятор, который не поддерживает C++ 11.

Причина, по которой вам необходимо std::unary_function, состоит в том, чтобы включить std::result_of для вашего класса, который использует для вывода типа результата, поскольку в C++ 98 отсутствует тип decltype.

Если вы посмотрите на std::unary_function вы увидите, что она определяет тип result_type из аргументов шаблона вы проходите, который находится в свернули используется std::result_of или std::bind непосредственно.

+0

На самом деле, даже без ссылок rvalue это не сработает, поэтому я думаю, что причиной является вывод тип результата. Если я правильно понимаю, тип можно автоматически вывести на C++ 11, а не в C++ 98? – OlivierB

+0

@OlivierB: Вот почему я написал ** одну ** причину. Да, типы не могут быть автоматически выведены на C++ 98, а в C++ 11 - с помощью 'decltype'. – ronag

0

Ну, как правило, ваш код плох:

Во-первых, вы можете иметь проблемы с временными объектами и г-значения при запросе неконстантная ссылки для их

, например

float f = StaticCast<float>()(4); 

даже не будет компилироваться.

Затем вы получаете объекта во время кастинга. Возможно, вы этого не хотите.

например Source бесплатно этого невыгодное из-за move семантику

+0

Ну, я должен согласиться ... Насколько я понимаю, нет идеального способа сделать это с GCC 4.2.1. – OlivierB

 Смежные вопросы

  • Нет связанных вопросов^_^