2010-10-29 3 views
0

Я новый новичок с boost. А вот мой тестовый код,проблема с лямбда-связью?

using namespace boost::lambda; 
    std::vector<std::string> strings; 
    strings.push_back("Boost"); 
    strings.push_back("C++"); 
    strings.push_back("Libraries"); 

    std::vector<int> sizes; 

    std::for_each(
    strings.begin(), 
    strings.end(), 
    bind(
    &std::vector<int>::push_back, 
    sizes, 
    bind<std::size_t>(&std::string::size, _1))); 

    std::for_each(sizes.begin(), sizes.end(), var(std::cout)<<_1); 

построить проект и дают ошибку:

ошибка C2665: «повышение :: лямбда :: function_adaptor :: применить»: ни один из 2-х перегрузок не может преобразовать все типы аргументов

Интересно, что случилось? Очень ценю.

+0

W шляпу, вы пытаетесь сделать со строками в векторе? – stefanB

+0

bind и lambda оба имеют заполнители '_1', связываются в анонимном пространстве имен, лямбда в пространстве имен лямбда. попробуйте не использовать целое boost :: lambda namespace – Anycorn

ответ

0
namespace lambda = boost::lambda; 
    std::vector<std::string> strings; 
    strings.push_back("Boost"); 
    strings.push_back("C++"); 
    strings.push_back("Libraries"); 

    std::vector<int> sizes; 

    std::for_each(
    strings.begin(), 
    strings.end(), 
    bind(
    &std::vector<int>::push_back, 
    sizes, 
    bind<std::size_t>(&std::string::size, _1))); 

    std::for_each(sizes.begin(), sizes.end(), lambda::var(std::cout)<< lambda::_1); 
+0

Когда я попробовал это, у меня не было значений в 'sizes' (g ++ (GCC) 4.1.2) ... – stefanB

+0

Я запускаю на windows vs2005, после всех ответов все работает. – leo

1

Первая проблема заключается в том, что std::vector::push_back перегруженной функция в C++ 0x (возникает перегрузка с опорным параметром именующим и перегрузкой с опорным параметром RValue).

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

Необходимо ввести функцию указатель-член к правильному типу, иначе это не будет работать с реализацией библиотеки C++ 0x (функция-указатель-член будет неоднозначной). Вам понадобятся:

(void (std::vector<int>::*)(const int&))&std::vector<int>::push_back 

Использование C++ 0x функциональная библиотека, следующие работы (он должен работать с Boost, а если заменить std:: с boost::, я просто не могу проверить, что):

std::for_each(
    strings.begin(), 
    strings.end(), 
    std::bind(
     (void (std::vector<int>::*)(const int&))&std::vector<int>::push_back, 
     std::ref(sizes), 
     std::bind(&std::string::size, std::placeholders::_1))); 

Обратите внимание, что это настоящий беспорядок, и это гораздо понятнее просто использовать цикл:

for(std::vector<int>::const_iterator i(strings.begin()); i != strings.end(); ++i) 
{ 
    sizes.push_back(i->size()); 
} 

Или, если у вас есть компилятор, который поддерживает лямбда-выражения:

std::for_each(strings.begin(), strings.end(), 
       [&](const std::string& s) { sizes.push_back(s.size()); }); 

Или, для большего удовольствия:

std::transform(strings.begin(), strings.end(), std::back_inserter(sizes), 
       [](const std::string& s) { return s.size(); }); 
+0

Спасибо, приложение работает, но я немного смущен этим кодом: (void (std :: vector :: *) (const int &)) & std :: vector :: push_back. Мне нужно больше узнать об этом. – leo

+0

@user: '& std :: vector :: push_back' принимает адрес именованной функции-члена. Часть, которая предшествует ей, - это бросок, точно так же, как если бы вы сказали '(int) 3.0', который забрасывает двойное значение' 3.0' для ввода 'int'.В этом случае мы переходим к типу «указатель на функцию, которая является членом« std :: vector »и принимает один аргумент типа' const int & 'и возвращает' void'. –

+0

Aha я вижу. много – leo

0

Или вы можете создать свой собственный функциональный объект:

template <typename T> 
struct c_inserter 
{ 
    T& c; 

    c_inserter(T& c) : c(c) {} 
    void operator()(string& v) { c.push_back(v.size()); } 
}; 

затем использовать его (обратите внимание на ostream_iterator и copy заменить другой lambda):

#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 
#include <iterator> 

#include <boost/lambda/lambda.hpp> 

int main() 
{ 
    std::vector<std::string> strings; 
    strings.push_back("Boost"); 
    strings.push_back("C++"); 
    strings.push_back("Libraries"); 

    std::vector<int> sizes; 

    std::for_each(
      strings.begin(), 
      strings.end(), 
      c_inserter< vector<int> >(sizes)); 

    copy(sizes.begin(), sizes.end(), ostream_iterator<int>(cout,":")); 
    cout << endl; 
}