Fra*_*mes 0 c++ c++-concepts c++20 std-ranges
我正在努力满足我的班级的 C++20 概念。
struct C1
{
int* begin();
int* end();
};
static_assert(std::ranges::range<C1>); // Compiles fine
struct C2 {};
namespace std::ranges // (A)
{
auto begin(C2&);
auto end(C2&);
}
static_assert(std::ranges::range<C2>); // Fails to compile
Run Code Online (Sandbox Code Playgroud)
该std::ranges::range<>
概念定义如下:
template <class _Rng>
concept range = requires(_Rng& __r) {
std::ranges::begin(__r);
std::ranges::end(__r);
};
Run Code Online (Sandbox Code Playgroud)
从字面意思上看,它指示我声明上面的函数 (A)。但这些都没有帮助。另一方面,像在类中一样定义两个成员函数C1
确实有效。我的问题是,我只是看不到概念所强加的要求与有助于 class 的解决方案之间的语义联系C1
。它告诉我做一件事,而实际上我需要做另一件事。
请对此提供一些解释。
背景:在我的生产代码中,我的类确实定义了一个begin()
和end()
函数,每个函数返回一个迭代器。但这个range
概念并不满足这些定义,也未能告诉我原因。
请参阅编译器资源管理器上的完整示例
std::ranges::begin
是一个定制点对象;它不是一个可以重载的函数。即使begin
是一个正确的函数,您也不能将函数重载插入std
命名空间或任何子命名空间(您可以专门化 中的模板std
,但前提是它至少涉及一种用户定义的类型)。
遵守的方法std::ranges::begin
就是遵守它的规则。在检查给定的范围类型是一个数组(它有专门的逻辑)之后,它将按顺序查找:
begin
函数。begin
可以通过参数相关的查找(即:)找到的函数,begin(range_object)
它返回一个迭代器。因此,如果您想将类型放入范围而不添加成员,则必须使用后者:将函数begin
放在与相关类型相同的命名空间中。此外,它需要返回一个可以验证为迭代器的类型。