c++11之C++11 是否允许更好的方法在没有非匿名帮助函数的情况下对相似数据重复相同的操作

kevingrace 阅读:121 2025-06-02 22:19:02 评论:0

(实在想不出更好的标题了,可以的话请帮忙)

这种重复的代码并不罕见……一个故意简单的例子:

vector<int> x,y,z; 
vector<string> a,b,c; 
 
for(auto i : x) 
 if(test(i)) 
  a.push_back(func(i)); 
for(auto i : y) 
 if(test(i)) 
  b.push_back(func(i)); 
for(auto i : z) 
 if(test(i)) 
  c.push_back(func(i)); 

你当然可以写一个函数 Convert(const vector<int> &in, vector<string> &out)但是我很好奇是否有一种方法可以使用匿名构造或函数局部定义来避免这种情况。

类似:

vector<int> x,y,z; 
vector<string> a,b,c; 
 
for(auto o : {{x,a},{y,b},{z,c}}) 
  ... 

什么是做到这一点的最巧妙的方法 - C++11 提供了超越“经典”C++/STL 方法的任何额外帮助?

注意:这个问题的重点是如何避免重复代码,而不是如何具体地在向量之间转换数据——这只是一个简单的例子。

请您参考如下方法:

经典的 STL 方法是使用 std::transform,如果你愿意,可以将其包装在 lambda 中

auto map = [](const vector<int>& in, vector<string>& out, string (*f)(int)) { 
  out.reserve(in.size()); 
  std::transform(in.begin(), in.end(), std::back_inserter(out), f); 
}; 
 
vector<int> x,y,z; 
vector<string> a,b,c; 
 
map(x, a, func); 
map(y, b, func); 
map(z, c, func); 

在 C++14 中,lambda 更容易编写:

auto map = [](const auto& in, auto& out, auto f) { 
  out.reserve(in.size()); 
  std::transform(in.begin(), in.end(), std::back_inserter(out), f); 
}; 

要在编辑的问题中做不同的操作,只需改变 lambda 的主体,你仍然避免重复逻辑,所以你只定义一次,然后将它应用到每对向量:

auto op = [](const auto& in, auto& out, auto f) { 
  for (auto i : in) 
    if (test(i)) 
      out.push_back(f(i)); 
 }; 
 
op(x, a, func); 
op(y, b, func); 
op(z, c, func); 

如果您想在 C++14 中走极端,您可以将向量捆绑在元组中,然后使用 Library Fundamentals TS 中的 apply,如下所示:

vector<int> x,y,z; 
vector<string> a,b,c; 
 
using std::experimental::apply; 
 
auto mapper = [&func, &test](auto... t) { 
  auto op = [](const auto& in, auto& out) { 
    for (auto i : in) 
      if (test(i)) 
        out.push_back(func(i)); 
   }; 
  std::tie( (apply(op, t), std::ignore) ... ); 
}; 
mapper( std::tie(x, a), std::tie(y, b), std::tie(z, c) ); 

但这越来越难以理解了!


标签:C++
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号