проблема лямбда-связывания? - PullRequest
0 голосов
/ 29 октября 2010

Я новичок в бусте.А вот мой тестовый код:

  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: 'boost :: lambda :: function_adaptor :: apply': ни один изперегрузки могут преобразовывать все типы аргументов

Интересно, что не так?Очень ценю.

Ответы [ 3 ]

1 голос
/ 29 октября 2010

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

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

Вам нужно привести функцию-указатель на член к правильному типу, иначе это не сработает с реализацией библиотеки 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:

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 голосов
/ 29 октября 2010

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

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;
}
0 голосов
/ 29 октября 2010
  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);
...