如何定义类型擦除范围::视图?

问题描述 投票:0回答:1

我有一个带有谓词的类,例如,

Object::isValid()
。我只需要迭代有效的对象,所以我使用范围/视图:

struct Object {
    bool isValid() const;
    // ...
};

// Usage:
std::vector<Object> objects = getObjects();
for (const auto &obj : objects |
                       std::ranges::view::filter(
                           [](const Object &obj) {
                               return obj.isValid();
                           })
    ) {
    // Use obj that is of type `const Object &`
}

到目前为止一切顺利。现在我需要分离有效对象视图的生产者和消费者:

auto getValidObjectsView() {
    return objects |
           std::ranges::views::filter(
               [](const Object &obj) {
                   return obj.isValid();
               }
           );
}

void consumeValidObjects(auto &&validObjectsView) {
    for (const auto &obj : validObjectsView) {
        // Use `obj`
    }
}

consumeValidObjects(getValidObjectsView());

这也有效,但现在我需要将函数的实现隐藏到单独的翻译单元中,以暴露标头中的签名。因此我不能再使用

auto
了。

问题是

getValidObjectsView()
函数的返回类型取决于
std::ranges::views::filter
以及该函数内部使用的 lambda,所以我不能简单地在函数签名中使用这种类型:

using ObjectsIterable = // whatever compiler reports as decltype<getValidObjectsView()> from the previous snippet

ObjectsIterable getValidObjectsView();
void consumeValidObjects(const ObjectsIterable &)

consumeValidObjects(getValidObjectsView());

我的问题是如何定义一个代理类型

ObjectsIterable
,它会删除生产者返回的实际底层类型,类似这样:

using ObjectsIterable = std::ranges::view::one_size_fits_all_view<Object>;
c++ c++20 type-erasure std-ranges
1个回答
0
投票

您可以通过将 lambda 转换为函数指针来类型擦除 lambda,而不是类型擦除返回的视图,这允许将函数的返回类型声明为

std::ranges::filter_view<
    std::ranges::ref_view<std::vector<Object>>, 
    bool (*)(const Object&)
>
getValidObjectsView() {
    return objects |
           std::ranges::views::filter(
               +[](const Object &obj) {
                   return obj.isValid();
               }
           );
}
© www.soinside.com 2019 - 2024. All rights reserved.