如何使用概念将模板约束为可迭代范围?

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
}