模板推导:移植到C ++ 11

时间:2017-03-29 06:29:39

标签: c++ c++11 c++14 stdbind

以下代码对于C ++ 14编译器来说是合法的

// g++ -std=c++14 -pedantic -pthread main.cpp
// output: 1 2 3 4 5 1 1 1 
#include <algorithm>
#include <vector>
#include <functional>
#include <iterator>
#include <iostream>

int main()
{
  std::vector<int> a = { 1, 2, 3, 2, 4, 5, 1, 1, 3, 5, 1, 5 }, b = { 2, 5, 5, 3 }, c;

  std::copy_if(a.begin(), a.end(), std::back_inserter(c), 
    std::bind(std::less<>(),   // this won't work in pre-C++14
      std::bind(
        std::count<std::vector<int>::iterator, int>, 
          std::bind(static_cast<std::vector<int>::iterator (std::vector<int>::*)()>(&std::vector<int>::begin), &c), 
          std::bind(static_cast<std::vector<int>::iterator (std::vector<int>::*)()>(&std::vector<int>::end), &c), 
          std::placeholders::_1
      ),
      std::bind(
        std::minus<>(), // this won't work in pre-C++14
          std::bind(
            std::count<std::vector<int>::iterator, int>, 
              a.begin(), 
              a.end(), 
              std::placeholders::_1
          ),
          std::bind(
            std::count<std::vector<int>::iterator, int>, 
              b.begin(), 
              b.end(), 
              std::placeholders::_1
          )
      )
    )
  );

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

意在从向量a的元素创建向量c,不包括与向量b中的元素的计数和值匹配的向量。例如。如果a包含三个2和b - 其中两个,则c中只有一个2。

a)如何使这个代码适应C ++ 11?直观的飞跃,少于&lt;&gt;和减去&lt;&gt;参数将是... :: difference_type没有工作,编译器消息也没有帮助

b)当前版本按顺序删除最后一个匹配项。什么代码会删除第一个匹配?

1 个答案:

答案 0 :(得分:7)

真正的答案是不要使用bind()。使用lambda:

std::copy_if(a.begin(), a.end(), std::back_inserter(c), [&](int elem){
    return std::count(c.begin(), c.end(), elem) <
        std::count(a.begin(), a.end(), elem) - std::count(b.begin(), b.end(), elem);
});

比使用std::bind()的解决方案短,适用于C ++ 11,并且更容易理解。而且我们也不必进行手动模板扣除。

我们也可以这样写:

std::copy_if(a.begin(), a.end(), std::back_inserter(c), [&](int& elem){
    return std::count(&elem + 1, &a[a.size()], elem) >=
        std::count(b.begin(), b.end(), elem);
});

请注意,我现在正在参考elem。这也使得更容易看到如何实现建议的扩展删除第一个匹配。这只是改变elem中我们正在比较的a的哪一侧:

std::copy_if(a.begin(), a.end(), std::back_inserter(c), [&](int& elem) {
    return std::count(&a[0], &elem, elem) >=
        std::count(b.begin(), b.end(), elem);
});