2014-10-20 3 views
2

Просто пытаюсь получить этот простой тест, работающий для доступа к функциональному оператору. Я вырыл вокруг boost :: bind (esp для overloaded section), но не нашел способа заставить это работать.boost :: bind with templated functors

#include <iostream> 

#include <boost/bind.hpp> 

template <typename FooType> 
struct Foo { 
    const FooType tmp_value; 

    Foo(const FooType& tmp_) : 
    tmp_value(tmp_) 
    { 
    } 

    template<typename Object> 
    void operator()(Object& operand) 
    { 
    std::cout << operand << std::endl; 
    operand += tmp_value; 
    } 
}; 

int main() { 


    double t = 4.0; 
    Foo<double> e(1.0); 
    std::cout << t << std::endl; 
    e(t); // Works 
    std::cout << t << std::endl; 

    double d = 5.0; 
    Foo<double> p(1.0); 
    auto f1 = boost::bind(&Foo::operator(), p, _1); // Blows up at compile 

    std::cout << d << std::endl; 
    f1(d); 
    std::cout << d << std::endl; 

} 

Compiler выход:

g++ -Wall --std=c++0x -I. bind.cc -o binder 
bind.cc:33:25: error: expected a class or namespace 
    auto f1 = boost::bind(&Foo::operator(), p, _1); // Blows up at compile 
         ^

Я знаю, что я просто не хватает что-то простое, любая помощь будет удивительным.

+2

Вы не можете взять адрес шаблона (и вы используете 'Foo' без указания аргумента шаблона). В любом случае у вас есть функтор, просто привяжите функтор напрямую. –

+0

Вам нужен метод оператора шаблона? Если вам нужно использовать имя типа Foo, например 'void operator() (const FooType & operand)' then 'boost :: bind <&Foo :: operator(), p, _1);' будет работать, а также должно помочь вам не допустить, t попытаться выполнить сложные назначения на несовместимых типах. – AJG85

ответ

4

Вы пытаетесь принять адрес шаблона функции-члена, не указав аргументы типа, что невозможно. Ваш код работает, если вы добавите аргументы типа для Foo и operator().

auto f1 = boost::bind(&Foo<double>::operator()<double>, p, _1); 
//      ^^^^^^^^   ^^^^^^^^ 

Но, как T.C. говорит в комментариях, у вас уже есть функтор, который может быть связан непосредственно как

auto f1 = boost::bind<void>(p, _1); // void is the return type of operator() 

Live demo

1

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

Однако, в зависимости от компилятора версий/наддува вы не можете получить decltype() благость по умолчанию, и вы должны добавить

typedef void result_type; 

к классу Foo функтора: Live On Coliru

В качестве альтернативы, вы можете #define BOOST_RESULT_OF_USE_DECLTYPE перед включением любых заголовков усиления.

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