Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以让'std::ranges::views::elements'与我类型的范围一起工作吗_C++_C++20_Std Ranges - Fatal编程技术网

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
(您也不应该这样做,尤其是在这种情况下,这些重载无论如何都不会帮助结构化绑定).

你能提供你得到的错误信息吗?另一种方法是提供一个成员函数,将
转换成一个
元组
,其中包含对其成员的引用。我想到了这一点,但忽略这一点似乎非常有用,因此我认为这是一个缺陷!我找不到任何关于限制的讨论,这似乎最终可以追溯到令人遗憾的是,它完全没有任何解释。@Daviserring
elements
是由P1035添加的,但这里的问题是没有针对元组的库协议,如。。。所以它只支持库元组。另外,ADL
get
只是。。。一个问题。我用“易碎解决方案”检查了一下,它的工作原理和你提到的完全一样。但事实上,它非常脆弱。现在,我只要在需要时使用views::transform,而不是让我的
Point
类型与通用的
views::elements
一起工作。我还尝试了非成员的
get
函数,但它不起作用。似乎@Barry的回答是正确的,调用
get(Point)
符合
std::
,因此不允许ADL t