【问题标题】:lambda bind problem?lambda绑定问题?
【发布时间】:2011-02-05 11:26:05
【问题描述】:

我是 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: 'boost::lambda::function_adaptor::apply' : 2 个重载都不能转换所有参数类型

不知道怎么了?真的很感激。

【问题讨论】:

  • 你想对向量中的字符串做什么?
  • bind 和 lambda 都有占位符 _1,bind 在匿名命名空间中,lambda 在 lambda 命名空间中。尽量不要使用整个 boost::lambda 命名空间

标签: c++ boost bind boost-lambda


【解决方案1】:

第一个问题是std::vector::push_back是C++0x中的重载函数(有左值引用参数的重载和右值引用参数的重载)。

第二个问题是标准库成员函数的类型是未指定的:允许实现者向成员函数添加带有默认参数的额外参数,并且允许他们添加成员函数的额外重载,因此您所做的任何转换不会是便携式的。消歧示例假设我们忽略了第二个问题。

您需要将指向成员函数的指针转换为正确的类型,否则这将不适用于 C++0x 库实现(指向成员函数的指针将是不明确的)。你需要:

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

使用 C++0x 函数库,以下工作(如果将 std:: 替换为 boost::,它也应该适用于 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());
}

或者,如果您有一个支持 lambda 表达式的编译器:

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(); });

【讨论】:

  • 谢谢,该应用程序工作正常,但我对这段代码有点困惑:(void (std::vector::*)(const int&))&std::vector ::推回。我需要了解更多。
  • @user: &amp;std::vector&lt;int&gt;::push_back 获取命名成员函数的地址。它前面的部分是一个类型转换,就像您说的(int)3.0 一样,它将双精度值3.0 转换为类型int。在这种情况下,我们将类型转换为“指向一个函数的指针,该函数是std::vector&lt;int&gt; 的成员,它接受一个const int&amp; 类型的参数并返回void
  • 我尝试了 lambda 表达式 std::for_each(strings.begin(), strings.end(), [&](const std::string& s) { sizes.push_back(s.size() ); });和 std::transform(...) 但产生语法错误:“[”“]”,所以我错过了一些头文件或其他原因?
  • @leo:您的编译器可能不支持 lambda 表达式。最新版本的 Visual C++、Intel C++ 和 g++ 都支持它们。
  • 很抱歉,我在 VS2005 和 ubuntu 10.04 上使用 g++ 4.4.3 运行了它,并且都出现了这个错误。我应该指定命名空间还是使用某些库编译代码?
【解决方案2】:
  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);

【讨论】:

    【解决方案3】:

    或者您可以创建自己的函数对象:

    template <typename T>
    struct c_inserter
    {
        T& c;
    
        c_inserter(T& c) : c(c) {}
        void operator()(string& v) { c.push_back(v.size()); }
    };
    

    然后使用它(注意ostream_iteratorcopy 替换另一个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;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-10-15
      • 2012-10-27
      • 1970-01-01
      • 1970-01-01
      • 2015-05-12
      • 1970-01-01
      • 2016-03-19
      相关资源
      最近更新 更多