如何使std :: distance成为可调用的应用或调用?

时间:2016-11-13 14:46:40

标签: lambda apply invoke c++17 function-templates

我使用了C ++ 17 / C ++ 1z功能applyinvoke 最后,我想直接将apply用于equal_range的结果 像这样:

cout << apply(std::distance, data.equal_range(4)) << '\n';

那没编译。我认为这是因为equal_range返回了pair而不是tuple,但事实证明并非如此。

如果我使用 Lambda 而不是std::distance,我的大型示例会编译所有内容。在考虑其原因时,我认为它与实例化模板函数distance有关。嗯,遗憾的是,如果没有它,这是行不通的,因为我很难用`std :: distance :: iterator&gt;

实例化它
#include <iostream>
#include <set>
#include <functional> // invoke
#include <experimental/tuple> // apply

using std::set; using std::cout;
using std::invoke;
using std::experimental::apply;

int main() {
  set<int> data { 1,2,3,4,5,6 };

  // the C++11-way, not possible in one line.
  auto r = data.equal_range(4);
  cout << std::distance(r.first, r.second) << '\n';

#if 0 // do not work
  cout << invoke(std::distance, r.first, r.second) << '\n';
  cout << apply(std::distance, r) << '\n';
  cout << apply(std::distance, make_tuple(r.first, r.second)) << '\n';
  cout << apply(std::distance, data.equal_range(4)) << '\n';
#endif

 // explicitly instantiate distance: intolerably cumbersome
 cout << apply(std::distance<set<int>::iterator>, data.equal_range(4)) << '\n';

  // using a lambda: too long for a single line
  auto d = [](auto b, auto e) { return std::distance(b, e); };
  cout << invoke(d, r.first, r.second) << '\n';
  cout << apply(d, r) << '\n';
  cout << apply(d, make_tuple(r.first, r.second)) << '\n';
  cout << apply(d, data.equal_range(4)) << '\n';
} 

是否有更好,更紧凑的方式将applyinvokedistance这样的模板函数一起使用而没有显式实例化或lambda?

1 个答案:

答案 0 :(得分:1)

#define OVERLOADS_OF(...)\
  [](auto&&...args)->decltype(auto){\
    return __VA_ARGS__( decltype(args)(args)... );\
  }

现在OVERLOADS_OF(std::distance)是一个可以传递给std::apply的lambda。

我已经看到至少有一个提议将这个(更漂亮的语法,而不是基于宏的)放入标准中;我不知道它的状态。