c++ - 我可以在不创建语法怪物的情况下转发(类型)通用重载函数吗?

标签 c++ c++20

这只是一个教育问题,否则可以通过利用 range-v3 等工具完全避免。

无论如何,请考虑以下示例,其中将可变数量的容器传递给返回迭代器元组的函数:

#include <tuple>
#include <iostream>
#include <vector>

template <typename ...T> 
auto begin(T&... containers) { return std::tuple( begin(containers)... ); }

int main() {
  std::vector<int> a{1,2,3};
  std::vector<long> b{1000,2000,3000};

  auto bg = begin(a,b);
  (void) bg;
  return 0;
}

通过为所有其他迭代器创建者(std::[end, cbegin, cend, rbegin, rend])添加函数,将会产生相当多的代码重复。因此,我正在寻找一种方法将通用迭代器 maker 函数转发到我的函数中。
我设法想出了这个:
template <auto F, typename ...T>
auto make(T&... containers) { return std::tuple( F(containers)... ); }
// called as this:
auto bg = make<[](auto& c){return std::begin(c);}> (a,b);

...这是更通用的,但为用户带来了可怕的语法,理想情况下,调用应该是这样的:
auto bg = make<std::begin>(a, b); // or
auto bg = make(std::begin, a, b);

但我一直无法让这些美女发挥作用......

最佳答案

but I have not been able to make these beauties work...



目前没有办法让这些美女发挥作用。这一切的根源在于std::begin et al 不是函数。它们是函数模板。这意味着它们代表的不是单一功能,而是它们的整个家族。当您有常规重载时也是如此。当一个函数名意味着多个函数时,它就不能被传递。重载集不是我们可以像类型或函数引用一样传递的有形事物。这真的不是一个可调用的。

将实际重载的调用包装到 lambda 中可以完全绕过这个问题。因为 lambda 是一个具有类型的对象,这些对象可以很好地传递。这从本质上解除了作为二等公民的过载设置。但它带有样板。

有一个提议 ( p1170 ) 自动将过载集提升为可调用的,但到目前为止它似乎没有获得牵引力。所以C++20没有办法。

至于样板,如果我们愿意使用宏,我们可以减少它。一个正确提升重载集的简单宏看起来像这样:
#define LIFT(...) [](auto&& ...args)                                           \
        noexcpet(noexcpet(__VA_ARGS__(std::forward<decltype(args)>(args)...))) \
     -> decltype(auto) {                                                       \
    return __VA_ARGS__(std::forward<decltype(args)>(args)...);                 \
}

当然,这本身就是很多样板,但它处理异常规范,以及不按值返回的函数的返回类型推导。它也完美的前锋。所以虽然它确实相当丑陋,但它允许我们写:
auto bg = make(LIFT(std::begin), a, b);

关于c++ - 我可以在不创建语法怪物的情况下转发(类型)通用重载函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58438120/

相关文章:

java - 使用 hockeyapp 的 cocos2dx 中的 C++ 崩溃报告

c++ - 为什么 + 运算符重载返回类型是类类型而不是整数?

c++ - 在 C++20 中将嵌套类型传递给父类而不重复自己(DRY)

c++ - 为什么在 C++ 20 中从标准库容器中删除了比较运算符?

c++ - 为什么 std::rel_ops::operators 在 C++20 中会被弃用?

c++ - QT 5.6 静态未解析的外部符号

c++ - 使用位域转换大型项目以使用更便携的东西

c++ - 如何通过 ref union 迭代 2 个 vector ?

C++ - 定义 - 私有(private)继承

c++ - 给聚合一个转换构造函数?