如何使用概念将模板约束为可迭代范围?
How to constraint a template to be iterable ranges using concepts?
说我有一些模板函数,returns 一些可迭代对象的中值传递给它。
类似于:
template<typename T>
decltype(auto) find_median_sorted(T begin)
{
// some code here
}
现在我想确保我将 T
约束为始终可迭代。我正在尝试学习如何在 C++ 中使用 concepts
,所以有什么方法可以在这里使用 concept
来确保 T
是可迭代的?
我确定还有其他方法可以检查它是否可迭代,但这是 concepts
的错误用例吗?
我也遇到了与可迭代元素相关的 post ,但我不确定这如何适用于我的情况。
I am trying to learn how to use concepts in C++, so is there some way I can use concept
here to make sure T is iterable?
您可以在此处从 <ranges>
header 获得标准概念 std::ranges::range
。有了它,您的函数将如下所示:
#include <ranges> // std::ranges::range
template<std::ranges::range T>
decltype(auto) find_median_sorted(T const& container) {
// some code here
}
要将范围限制为仅用于随机访问可迭代范围,您可以再次使用 std::ranges::random_access_range
来自 <ranges>
header
#include <ranges> // std::ranges::random_access_range
template<std::ranges::random_access_range T>
decltype(auto) find_median_sorted(T const& container) {
// some code here
}
或通过迭代器概念std::random_access_iterator
如下:
#include <iterator> // std::random_access_iterator
template<typename T>
decltype(auto) find_median_sorted(T const& container)
requires std::random_access_iterator<std::ranges::iterator_t<T>>
{
// some code here
}
编辑:问题中的原始代码看起来更像迭代器,因此为什么要基于迭代器的答案。就目前而言,基于范围的答案更适合 OP 的要求。
“老式”迭代器与其现代解释之间的一个重要区别是哨兵(也称为结束迭代器)不一定必须与开始迭代器的类型相同。
所以你应该使用 2 个单独的约束。一个用于迭代器本身,另一个用于哨兵,使用 std::sentinel_for
:
至于迭代器本身,您将希望使用最松散的迭代器概念,它允许您执行您想做的工作。如果可能,理想情况下 std::input_iterator
。
应用约束只是简单地将模板中的 typename
替换为适当的概念:
#include <iterator>
template<std::input_iterator I, std::sentinel_for<I> S>
auto find_median_sorted(I begin, S end){
// some code here
}
说我有一些模板函数,returns 一些可迭代对象的中值传递给它。
类似于:
template<typename T>
decltype(auto) find_median_sorted(T begin)
{
// some code here
}
现在我想确保我将 T
约束为始终可迭代。我正在尝试学习如何在 C++ 中使用 concepts
,所以有什么方法可以在这里使用 concept
来确保 T
是可迭代的?
我确定还有其他方法可以检查它是否可迭代,但这是 concepts
的错误用例吗?
我也遇到了与可迭代元素相关的 post
I am trying to learn how to use concepts in C++, so is there some way I can use
concept
here to make sure T is iterable?
您可以在此处从 <ranges>
header 获得标准概念 std::ranges::range
。有了它,您的函数将如下所示:
#include <ranges> // std::ranges::range
template<std::ranges::range T>
decltype(auto) find_median_sorted(T const& container) {
// some code here
}
要将范围限制为仅用于随机访问可迭代范围,您可以再次使用 std::ranges::random_access_range
来自 <ranges>
header
#include <ranges> // std::ranges::random_access_range
template<std::ranges::random_access_range T>
decltype(auto) find_median_sorted(T const& container) {
// some code here
}
或通过迭代器概念std::random_access_iterator
如下:
#include <iterator> // std::random_access_iterator
template<typename T>
decltype(auto) find_median_sorted(T const& container)
requires std::random_access_iterator<std::ranges::iterator_t<T>>
{
// some code here
}
编辑:问题中的原始代码看起来更像迭代器,因此为什么要基于迭代器的答案。就目前而言,基于范围的答案更适合 OP 的要求。
“老式”迭代器与其现代解释之间的一个重要区别是哨兵(也称为结束迭代器)不一定必须与开始迭代器的类型相同。
所以你应该使用 2 个单独的约束。一个用于迭代器本身,另一个用于哨兵,使用 std::sentinel_for
:
至于迭代器本身,您将希望使用最松散的迭代器概念,它允许您执行您想做的工作。如果可能,理想情况下 std::input_iterator
。
应用约束只是简单地将模板中的 typename
替换为适当的概念:
#include <iterator>
template<std::input_iterator I, std::sentinel_for<I> S>
auto find_median_sorted(I begin, S end){
// some code here
}