这是我的函数,它按对的第一个元素对向量进行排序。
std::vector<std::pair<int,std::string>>
sort_pairs(std::vector<std::pair<int,std::string>>&& items)
{
std::sort(std::begin(items),std::end(items));
return items;
}
但是当我尝试将其概括为接受任何类型的分配器和任何类型的分配器时,我得到了一堆错误(太多了,无法将它们粘贴到此处(。我使用 rvalue 引用作为参数,因为该函数在其他函数中调用,复制参数也可以工作,但我认为效率会降低。这是我尝试过的一些方法。
template <typename Allocator,
typename P1 = typename Allocator::value_type::first_type,
typename P2 = typename Allocator::value_type::second_type>
Allocator<std::pair<P1,P2>> sort_pairs(Allocator<std::pair<P1,P2>>&& items)
{
std::sort(std::begin(items),std::end(items));
return items;
}
如果您在代码中添加一些 c++20 提示,我将不胜感激。像要求。
底层类型是一对突出的事实吗?算法的主体不会以任何方式利用它。我们可以从以下方面开始:
template <typename R>
std::decay_t<R> sort(R&& items)
{
std::sort(std::begin(items),std::end(items));
return items;
}
在 C++20 中,我们可以通过要求R
是一个迭代器可排序的范围来适当约束 - 是的,有一个概念:
template <std::ranges::range R>
requires std::sortable<std::ranges::iterator_t<R>>
std::decay_t<R> sort(R&& items)
{
std::sort(std::ranges::begin(items), std::ranges::end(items));
return items;
}
如果您确实希望要求这是一个对的范围,则可以将其添加为单独的约束:
template <std::ranges::range R>
requires std::sortable<std::ranges::iterator_t<R>> &&
is_specialization_of<std::ranges::range_value_t<R>, std::pair>
std::decay_t<R> sort(R&& items)
{
std::sort(std::ranges::begin(items), std::ranges::end(items));
return items;
}
我将把is_specialization_of
的实现作为一个练习。
你应该使用什么来表达你的Allocator
,是一个"模板模板参数"。
如下
template <template <typename...> class Allocator,
typename P1, typename P2>
Allocator<std::pair<P1, P2>>
sort_pairs (Allocator<std::pair<P1, P2>> && items)
{
std::sort(std::begin(items),std::end(items));
return items;
}
从 C++17 开始,您可以使用typename
而不是class
定义它
// ..............................VVVVVVVV
template <template <typename...> typename Allocator,
但class
仍然有效,恕我直言,更可取。
请注意,Allocator
截获std::vector
(模板类,而不是std::vector<std::pair<int, std::string>>
的特定专用化(,因此您无法像示例中那样从中提取P1
和P2
// ....................VVVVVVVVV not usable this way
typename P1 = typename Allocator::value_type::first_type
你应该写
typename Allocator<std::pair<P1, P2>>::value_type::first_type
但是,显然,您不能使用它来为P1
提供默认类型,因为您必须知道P1
。
幸运的是,可以从items
参数推导出P1
和P2
,因此不需要默认类型。