6

考虑具有,和值的Point类型。如果我有一系列对象,例如,我需要添加什么才能使其与范围适配器一起使用?xyzPointstd::vector<Point>Pointstd::ranges::views::elements

目的是做类似的事情

std::vector<Point> v{...};
for (auto x : v | std::ranges::views::elements<0>) {
    // do something with all `x` values
}

文档提到适用于“类似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;
};
}

这足以使结构化绑定起作用,但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>();
}

现在可以使用 std::get<0>(p) 来提取x值,但这对于std::ranges::views::elements. 使一系列Point对象工作还需要std::ranges::views::elements什么?


PS:我知道我可以在views::transform这里使用 a ,但我在这里的主要目的是通用并理解这些东西是如何组合在一起的。通用并理解这些东西是如何组合在一起的。

4

2 回答 2

4
于 2021-05-28T16:29:43.720 回答
0

目的是您在命名空间中提供一个非成员get函数模板(用于 ADL)。这结构化绑定更严格,后者也支持成员。get

您的专业化不起作用,因为它不是专业化:它是一个重载,因此在命名空间中是不允许的std(实际上在名称查找中没有从 within 找到<ranges>)。

于 2021-05-28T16:11:35.440 回答