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

问题描述 投票:0回答:2

这是我所拥有的功能,它按对的第一个元素对向量对进行排序。

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;
}

但是当我尝试将其推广为接受任何类型的分配器和该对的任何类型时,我都会收到一堆错误(将其粘贴到此处太多了)。我使用右值引用作为参数,因为该函数在其他函数内部调用,使用复制参数也可以,但是我认为效率较低。这是我尝试过的一些方法。

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提示,我们将不胜感激。像需求一样。

c++ templates c++20
2个回答
1
投票

表达Allocator,您应该使用的是“ template template parameter”。

如下

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

幸运的是,可以从P1参数推导出P2items,因此您不需要默认类型。


1
投票

底层类型是一对显着的事实吗?该算法的主体没有以任何方式使用它。我们可以从以下开始:

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的实现留作练习。

© www.soinside.com 2019 - 2024. All rights reserved.