gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 00:11:22 25 4
gpt4 key购买 nike

这只是一个教育问题,否则可以通过利用 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com