使用模板化分配器和对向量进行排序的函数



这是我的函数,它按对的第一个元素对向量进行排序。

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>>的特定专用化(,因此您无法像示例中那样从中提取P1P2

// ....................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参数推导出P1P2,因此不需要默认类型。

最新更新