【发布时间】:2021-09-13 14:11:23
【问题描述】:
我正在尝试迭代过滤(按类型)std::vector<std::variant<T...>>。
我遇到的问题是std::get 是重载函数(并且有许多我需要输入的隐式模板参数)所以我需要将它转换为特定的东西。
这看起来很难看,所以我尝试将holds_alternative 和get 组合成一个函子,该函子返回filter(对于holds_alternative)和transform(对于get)视图的视图。
那是行不通的。
问题:
- 我可以做我想做的事而不提供我的结构并且不需要指定
std::get重载的丑陋强制转换,丑陋需要指定std::holds_alternative、std::get的所有模板参数吗? - 如果对上一个问题的回答是否定的:为什么我的尝试不起作用
注意:
我的代码不会像std::get 那样尝试正确处理const 和&&,我可以只在const l 值上工作。
我的code:
#include <algorithm>
#include <iostream>
#include <ranges>
#include <variant>
#include <vector>
struct Red {
int x = 0;
};
struct Green {
int x = 1;
};
struct Blue {
int x = 2;
};
using Color = std::variant<Red, Green, Blue>;
template <typename T> struct engaged_t {
template <typename... Ts>
constexpr bool operator()(const std::variant<Ts...> &variant) {
return std::holds_alternative<T>(variant);
}
};
template <typename T> inline constexpr auto engaged = engaged_t<T>{};
template <typename T> struct variant_get_t {
template <typename... Ts>
constexpr decltype(auto) operator()(std::variant<Ts...> &variant) {
return std::get<T>(variant);
}
};
template <typename T> inline constexpr auto variant_get = variant_get_t<T>{};
template <typename T> struct variant_filter_t {};
template <typename T>
inline constexpr auto variant_filter = variant_filter_t<T>{};
template <typename R, typename T>
decltype(auto) operator|(const R &r, variant_filter_t<T>) {
return r | std::views::filter(engaged<T>) |
std::views::transform(variant_get<T>);
}
int main() {
std::vector<Color> colors{Red{}, Green{}, Blue{}, Green{}};
// does not compile
// for (const auto green: colors | variant_filter<Green>){
// std::cout << std::get<Green>(green).x << std::endl;
// }
// kaboom if we try to do anything, just to show we can pipe colors to
// variant_get
for (const auto bad_green : colors |
std::views::transform(variant_get<Green>) |
std::views::take(0)) {
}
// we can also pipe colors to engaged
for (const auto bluev : colors | std::views::filter(engaged<Blue>)) {
std::cout << std::get<Blue>(bluev).x << std::endl;
}
// and if we manually doe what variant_filter should_do that also seems to
// work
for (const auto blue : colors | std::views::filter(engaged<Blue>) |
std::views::transform(variant_get<Blue>)) {
std::cout << blue.x << std::endl;
}
}
【问题讨论】:
-
所以你想要一个 functor 有
filter后跟transform视图? -
这是很多问题。你想回答哪一个?
-
@Jarod42 我想要一种作曲方法 | std::views::filter(参与) | std::views::transform(variant_get
) 无需键入 两次。 -
@Barry:好吧,如果我的假设是正确的,如果不使用自定义结构,我就不能很好地写出我想要的东西我想知道为什么仿函数不起作用,因为当我“手动”执行它时,它似乎工作。
-
您在参数上的
variant_get_t::operator()中错过了const
标签: c++ c++20 std-ranges