Каков тип возврата boost :: bind? - PullRequest
25 голосов
/ 20 июня 2011

Я хочу сохранить «связующее» функции в переменной, чтобы использовать ее повторно в следующем коде, используя средства перегрузки операторов. Вот код, который на самом деле делает то, что я хочу:

#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

class X 
{       
    int n; 
public: 
    X(int i):n(i){}
    int GetN(){return n;}  
};

int main()
{
    using namespace std;
    using namespace boost;

    X arr[] = {X(13),X(-13),X(42),X(13),X(-42)};
    vector<X> vec(arr,arr+sizeof(arr)/sizeof(X));

    _bi::bind_t<int, _mfi::mf0<int, X>, _bi::list1<arg<1> > > bindGetN = bind(&X::GetN,_1);

    cout << "With  n =13 : " 
         << count_if(vec.begin(),vec.end(),bindGetN == 13)
         << "\nWith |n|=13 : " 
         << count_if(vec.begin(),vec.end(),bindGetN == 13 || bindGetN == -13)
         << "\nWith |n|=42 : " 
         << count_if(vec.begin(),vec.end(),bindGetN == 42 || bindGetN == -42) 
         << "\n";

    return 0;                                                                    
} 

Что меня беспокоит, так это, конечно, строка:

bi::bind_t<int, _mfi::mf0<int, X>, _bi::list1<arg<1> > > bindGetN = bind(&X::GetN,_1);

Я получил тип, просто сделав ошибку типа и проанализировав сообщение об ошибке. Это, конечно, не очень хороший путь. Есть ли способ получить тип для "bindGetN"? Или, может быть, есть разные способы создания аналогичной функциональности?

Редактировать: Я забыл упомянуть, что, так сказать, "стандартное" предложение использовать function в этом случае не работает - потому что я хотел бы, чтобы мой оператор перегружался.

1 Ответ

17 голосов
/ 20 июня 2011

Короткий ответ: вам не нужно знать (реализация определена). Это выражение привязки (std::tr1::is_bind_expression<T>::value возвращает значение true для фактического типа).

Посмотрите на

  1. std::tr1::function<>
  2. BOOST_AUTO ()
  3. c ++ 0x 'auto' ключевые слова (вывод типа)
    • это близко к корпусу decltype() может помочь вам двигаться дальше

1

std::tr1::function<int> f; // can be assigned from a function pointer, a bind_expression, a function object etc

int realfunc();
int realfunc2(int a);

f = &realfunc;
int dummy;
f = tr1::bind(&realfunc2, dummy);

2

BOOST_AUTO () направлена ​​на поддержку семантики c ++ 0x auto без поддержки c ++ 0x:

BOOST_AUTO(f,boost::bind(&T::some_complicated_method, _3, _2, "woah", _2));

3.

По сути то же самое, но с поддержкой компилятора:

template <class T> struct DoWork { /* ... */ };

auto f = boost::bind(&T::some_complicated_method, _3, _2, "woah", _2));

DoWork<decltype(T)> work_on_it(f); // of course, using a factory would be _fine_

Обратите внимание, что auto, вероятно, был изобретен для такой ситуации: фактический тип - «вы не хотите знать» и может варьироваться в зависимости от компиляторов / платформ / библиотек

...