Как сохранить диапазон как поле в классе?

Я хотел бы сохранить диапазон в виде поля в классе, чтобы впоследствии я мог использовать его несколько раз. Однако, в отличие от локальных переменных, я не могу просто указать его тип как auto, С другой стороны, типы диапазонов, которые создает библиотека, очень сложны. Мне потребовалось бы непропорционально много времени, чтобы выяснить правильный тип вручную + это было бы неосуществимо в будущем, если бы я решил изменить способ получения диапазона.

Итак, я подумал, может быть, я мог бы использовать decltype чтобы помочь себе:

class MyClass {
    public:
    using MyRange = decltype(std::declval<std::vector<int*>>() | ranges::v3::view::filter([=](int* elem) { return true; }));
    MyRange range;
}

(примечание: мой факт std::declval на самом деле более сложный, но я хотел бы сделать пример кратким.)

Но я получаю ошибку:a lambda cannot appear in an unevaluated context

Итак, мой вопрос:

  • Как я могу избежать использования лямбды и получить мой decltype за работой?
  • Или, может быть, есть лучший / более чистый способ получить тип диапазона, чтобы объявить его как поле в классе?

1 ответ

Здесь полезен язык: если бы лямбда была допущена в decltype, это не помогло бы вам, потому что у вас не было бы способа вывести значение типа MyRange кроме как через default-initialization. Поскольку само появление лямбда-выражения имеет уникальный тип, вы не можете создать объект функции правильного типа для передачи view::filter чтобы вернуть то, что вы могли бы хранить в MyRange,

Обходной путь - "не делай этого"; например, где-нибудь хранить свой функциональный объект и ссылаться на него в decltype, В C++17, например:

struct MyClass {
    static constexpr auto pred = [](int* elem) { return true; };
    using MyRange = decltype(std::declval<std::vector<int*>>() | ranges::v3::view::filter(pred));
    MyRange range;
};
Другие вопросы по тегам