gpt4 book ai didi

c++ - boost::range::join 一个自定义调用中的多个范围

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

gnzlbg 中的解决方案部分的SO问题boost::range::join for multiple ranges意味着它可以在一个客户端代码调用中加入多个范围,调用一个自定义函数可变参数模板,该模板调用 boost::joinboost::make_iterator_range。根据该问题、答案和评论,先验可以加入 2 个范围,需要后者以确保使用先验的非 const 重载。第二个容器之后的任何容器都应该通过 std::forward 完美转发。但是我的客户端代码最多只能使用 3 个参数成功调用它。任何更多的东西都无法编译。出了什么问题以及如何解决?现在是否有加入许多范围的任何 Boost 实体?

我已经复制并粘贴了该 OP 的实现,在此处对其进行编辑只是为了 boost 空白可读性并添加相关标题:

#include <utility>
#include <boost/range/join.hpp>

template<class C>
auto join(C&& c)
-> decltype(boost::make_iterator_range(std::begin(c), std::end(c)))
{
return boost::make_iterator_range(std::begin(c), std::end(c));
}

template<class C, class D, class... Args>
auto join(C&& c, D&& d, Args&&... args)
-> decltype
(
boost::join
(
boost::join
(
boost::make_iterator_range(std::begin(c), std::end(c)),
boost::make_iterator_range(std::begin(d), std::end(d))
),
join(std::forward<Args>(args)...)
)
)
{
return boost::join
(
boost::join
(
boost::make_iterator_range(std::begin(c), std::end(c)),
boost::make_iterator_range(std::begin(d), std::end(d))
),
join(std::forward<Args>(args)...)
);
}

并添加了我的客户端代码:

#include <deque>
#include <array>
#include <vector>
#include <iostream>

int main()
{
std::deque<int> deq { 0, 1, 2, 3, 4 };
std::array<int, 4> stl_arr { 5, 6, 7, 8 };
int c_arr[3] { 9, 10, 11 };
std::vector<int> vec { 12, 13 };

for (auto& i : join(deq, stl_arr, c_arr))
{
++i;
std::cout << i << ", "; // OK, prints 1 thru 12
}

//join(deq, stl_arr, c_arr, vec); // COMPILER ERROR
}

最佳答案

有两件事正在发生。首先是以下声明不会按预期工作:

template<class C>
auto join(C&& c)
-> decltype(boost::make_iterator_range(std::begin(c), std::end(c)));

template<class C, class D, class... Args>
auto join(C&& c, D&& d, Args&&... args)
-> decltype
(
boost::join
(
boost::join
(
boost::make_iterator_range(std::begin(c), std::end(c)),
boost::make_iterator_range(std::begin(d), std::end(d))
),
join(std::forward<Args>(args)...)
// ^^^^-- (1)
)
);

问题的症结在于点 (1) join 的第二次过载不在范围内。使用三个参数没有问题,因为 Args pack 的长度为 1,因此结果 join(std::forward<Arg0>(arg0))扩展使用范围内的第一个重载。

有四个或更多参数的结果join(std::forward<Arg0>(arg0), ..., std::forward<ArgN>(argN))扩展需要第二次重载,但它不在 selfsame 的后期返回类型的范围内。

解决这个问题的一种方法是将函数模板集转换为成员函数模板集,因为类范围更宽松:

struct join_type {
template<class C>
auto operator()(C&& c) const
-> decltype(boost::make_iterator_range(std::begin(c), std::end(c)))
{
return boost::make_iterator_range(std::begin(c), std::end(c));
}

template<class C, class D, class... Args>
auto operator()(C&& c, D&& d, Args&&... args) const
-> decltype
(
boost::join
(
boost::join
(
boost::make_iterator_range(std::begin(c), std::end(c)),
boost::make_iterator_range(std::begin(d), std::end(d))
),
(*this)(std::forward<Args>(args)...)
)
)
{
return boost::join
(
boost::join
(
boost::make_iterator_range(std::begin(c), std::end(c)),
boost::make_iterator_range(std::begin(d), std::end(d))
),
(*this)(std::forward<Args>(args)...)
);
}
};

constexpr join_type join {};

请注意,重要的是类范围,而不是我们选择使用 operator()作为我们的成员函数模板的名称。您也可以使用名为 foo 的静态成员函数模板并在转发给它的类之外有一个普通的函数模板。


现在我们可以揭露第二个问题,因为实现有问题并且只能处理奇数个参数!连join(a, b)不会起作用,但该错误可能已被 ADL 先前隐藏(即客户端最终会有效地调用 boost::join(a, b),这显然有效)( Live On Coliru )。

让我们重写 fold :

struct join_type {
template<class C>
auto operator()(C&& c) const
-> decltype(boost::make_iterator_range(begin(c), end(c)))
{
return boost::make_iterator_range(begin(c), end(c));
}

template<typename First, typename Second, typename... Rest>
auto operator()(First&& first, Second&& second, Rest&&... rest) const
-> decltype( (*this)(boost::join(boost::make_iterator_range(begin(first), end(first)), boost::make_iterator_range(begin(second), end(second))), std::forward<Rest>(rest)...) )
{
return (*this)(boost::join(boost::make_iterator_range(begin(first), end(first)), boost::make_iterator_range(begin(second), end(second))), std::forward<Rest>(rest)...);
}
};

constexpr join_type join {};

Live On Coliru

关于c++ - boost::range::join 一个自定义调用中的多个范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37801073/

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