C++ 我可以让'std::ranges::views::elements'与我类型的范围一起工作吗
考虑具有C++ 我可以让'std::ranges::views::elements'与我类型的范围一起工作吗,c++,c++20,std-ranges,C++,C++20,Std Ranges,考虑具有x、y和z值的点类型。如果我有一系列Point对象,例如std::vector,我需要向Point添加什么才能使其与std::ranges::views::elements范围适配器一起工作 目的是做类似的事情 std::vector v{…}; 用于(自动x:v |标准::范围::视图::元素){ //用所有的'x'值做一些事情 } 提到std::ranges::views::elements与“类似元组”的值一起工作。我认为它应该像我们制作我们的类型一样工作,但我似乎遗漏了一些东西
x
、y
和z
值的点
类型。如果我有一系列Point
对象,例如std::vector
,我需要向Point
添加什么才能使其与std::ranges::views::elements
范围适配器一起工作
目的是做类似的事情
std::vector v{…};
用于(自动x:v |标准::范围::视图::元素){
//用所有的'x'值做一些事情
}
提到std::ranges::views::elements
与“类似元组”的值一起工作。我认为它应该像我们制作我们的类型一样工作,但我似乎遗漏了一些东西
我已尝试使用以下代码
类点{
双x=0;
双y=0;
双z=0;
公众:
点(双x,双y,双z):x(x),y(y),z(z){
模板
双get()常量{
如果constexpr(N==0)
返回x;
如果constexpr(N==1),则为else
返回y;
如果constexpr(N==2),则为else
返回z;
}
};
名称空间标准{
模板
结构元组大小:std::integral_常量{};
模板
结构元组元素{
使用类型=双;
};
}
这足以使结构化绑定工作,但是std::ranges::views::elements
仍然无法工作。然后我认为可能std::ranges::views::elements
需要std::get(p)
才能工作,我在std
名称空间下面添加了一个专门化
模板
双进站(常数点和p){
如果constexpr(N==0)
返回p.get();
如果constexpr(N==1),则为else
返回p.get();
如果constexpr(N==2),则为else
返回p.get();
}
现在可以使用std::get(p)来提取x
值,但这对于std::ranges::views::elements
来说还是不够的。要使一系列点
对象与标准::范围::视图::元素
一起工作,还需要什么
PS:我知道我可以在这里使用
views::transform
,但我在这里的主要目的是泛型并理解这些东西是如何组合在一起的。泛型并理解这些东西是如何组合在一起的。目的是在命名空间中提供一个非成员get
函数模板(用于ADL)。这比结构化绑定更严格,后者也支持成员get
您的专门化不起作用,因为它不是专门化:它是一个重载,因此在命名空间std
中是不允许的(实际上从
中通过名称查找找不到)
我可以让std::ranges::views::elements
与我类型的范围一起工作吗
不,你不能†
指定元素
的方式,在中,它受以下约束:
模板
概念具有元组元素=//仅显示
需要(T){
typename元组大小::type;
需要Nconvertible\uuo;
};
但我们必须牢记图书馆的一般规则,即:
每当提及标准库中定义的名称x
时,假定名称x
完全限定为 <代码>::性病::代码>x,除非另有明确说明。例如,如果库函数F
的Effects:element被描述为调用库函数G
,则函数 <代码>::性病::G是指
get(t)
没有对get
的非限定调用,而是对:std::get(t)
的调用(没有“除非另有明确说明”)
这意味着这是在测试std::get
(对于键
),而这不会找到用户提供的结构化绑定支持(应该是相关命名空间中的成员e.get()
或非限定的get(e)
)。您不能仅仅将重载添加到std
中来实现这一点
所以。。。目前不支持
†从技术上讲,如果您将超负荷的
std::get(Point)
粘贴到命名空间std
中,并确保在包含
之前对其进行了定义,则这只会起作用。但这是非常脆弱的,因为您必须小心地控制include顺序(您不能真正做到这一点),并且需要将重载添加到std
(您也不应该这样做,尤其是在这种情况下,这些重载无论如何都不会帮助结构化绑定).你能提供你得到的错误信息吗?另一种方法是提供一个成员函数,将点
转换成一个元组
,其中包含对其成员的引用。我想到了这一点,但忽略这一点似乎非常有用,因此我认为这是一个缺陷!我找不到任何关于限制的讨论,这似乎最终可以追溯到令人遗憾的是,它完全没有任何解释。@Daviserringelements
是由P1035添加的,但这里的问题是没有针对元组的库协议,如。。。所以它只支持库元组。另外,ADLget
只是。。。一个问题。我用“易碎解决方案”检查了一下,它的工作原理和你提到的完全一样。但事实上,它非常脆弱。现在,我只要在需要时使用views::transform,而不是让我的Point
类型与通用的views::elements
一起工作。我还尝试了非成员的get
函数,但它不起作用。似乎@Barry的回答是正确的,调用get(Point)
符合std::
,因此不允许ADL t