使用模板化分配器和对对向量对进行排序的函数
Function that sorts a vector of pairs with templated allocator and pairs
这是我的函数,它按对的第一个元素对对的向量进行排序。
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 提示,我将不胜感激。点赞要求
您应该使用“template template parameter”来表达您的 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
(模板 class,而不是 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
.
幸运的是,P1
和 P2
可以从 items
参数推导出来,因此您不需要默认类型。
底层类型是显着对这一事实吗?算法的主体不以任何方式使用它。我们可以从以下开始:
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
的实施留作练习。
这是我的函数,它按对的第一个元素对对的向量进行排序。
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 提示,我将不胜感激。点赞要求
您应该使用“template template parameter”来表达您的 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
(模板 class,而不是 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
.
幸运的是,P1
和 P2
可以从 items
参数推导出来,因此您不需要默认类型。
底层类型是显着对这一事实吗?算法的主体不以任何方式使用它。我们可以从以下开始:
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
的实施留作练习。