dar*_*amo 6 c++ c++20 std-ranges
考虑Point带有x,y和z值的类型。如果我有一系列Point对象,例如std::vector<Point>,我需要添加什么Point才能使其与std::ranges::views::elements范围适配器一起使用?
目的是做类似的事情
std::vector<Point> v{...};
for (auto x : v | std::ranges::views::elements<0>) {
// do something with all `x` values
}
Run Code Online (Sandbox Code Playgroud)
该文档提到std::ranges::views::elements适用于“类似元组”的值。我假设它的工作方式应该类似于我们如何使我们的类型与结构化绑定一起工作,但我似乎遗漏了一些东西
我已尝试使用以下代码
class Point {
double x=0;
double y=0;
double z=0;
public:
Point(double x, double y, double z) : x(x), y(y), z(z) {}
template <std::size_t N>
double get() const {
if constexpr(N == 0)
return x;
else if constexpr(N == 1)
return y;
else if constexpr(N == 2)
return z;
}
};
namespace std {
template <>
struct tuple_size<Point> : std::integral_constant<std::size_t, 3> {};
template <std::size_t N>
struct tuple_element<N, Point> {
using type = double;
};
}
Run Code Online (Sandbox Code Playgroud)
这足以使结构化绑定工作,但std::ranges::views::elements仍然不起作用。然后我认为可能std::ranges::views::elements需要std::get<n>(p)工作,我在下面的std命名空间中添加了一个专业化
template <std::size_t N>
double get(const Point &p) {
if constexpr(N == 0)
return p.get<0>();
else if constexpr(N==1)
return p.get<1>();
else if constexpr(N==2)
return p.get<2>();
}
Run Code Online (Sandbox Code Playgroud)
现在可以使用 std::get<0>(p) 来提取x值,但这对于std::ranges::views::elements. 使一系列Point对象一起工作还需要std::ranges::views::elements什么?
PS:我知道我可以在views::transform这里使用 a ,但我在这里的主要目的是通用并了解这些东西是如何组合在一起的。通用并了解这些东西是如何组合在一起的。
\n\n我可以
\nstd::ranges::views::elements和我的类型一起工作吗
不,你不能 \xe2 \x80\xa0。
\n在[range.elements.view]elements中指定的方式,它受到以下约束:
template<class T, size_t N>\n concept has-tuple-element = // exposition only\n requires(T t) {\n typename tuple_size<T>::type;\n requires N < tuple_size_v<T>;\n typename tuple_element_t<N, T>;\n { get<N>(t) } -> convertible_\xc2\xadto<const tuple_element_t<N, T>&>;\n };\nRun Code Online (Sandbox Code Playgroud)\n但我们必须记住图书馆的一般规则,来自[contents]/3:
\n\n\n\n
x每当提到标准库中定义的名称时,除非另有明确说明,否则该名称x都被假定为完全限定为\xe2\x80\x8b x。::\xe2\x80\x8bstd\xe2\x80\x8b::\xe2\x80\x8b例如,如果库函数的Effects : 元素F被描述为调用库函数,则意味着Gfunction\xe2\x80\x8b 。::\xe2\x80\x8bstd\xe2\x80\x8b::\xe2\x80\x8bG
不存在get<N>(t)对 的无限制调用get,而是对 的调用::std::get<N>(t)(不存在“除非另有明确描述”)。
这意味着这是测试std::get<0>(for keys),并且不会找到用户提供的结构化绑定支持(它应该是关联命名空间中的成员e.get<0>()或不合格的成员)。get<0>(e)您不能仅仅添加重载来std使其工作。
所以...目前不支持。
\n\xe2\x80\xa0从技术上讲,如果您将重载粘贴std::get<N>(Point)到名称空间中std并确保它在包含之前已定义,则这将是 Just Work TM。但这是非常脆弱的,因为您必须仔细控制包含顺序(您实际上无法做到这一点),并且涉及添加重载(您也不应该这样做,特别是在这种情况下,这些重载不会无论如何,对结构化绑定没有帮助)。<ranges>std