编辑2:
新编辑:看起来C++20有一个新的范围库,从功能的角度来看,它可以做我想做的事情。如何在C++17或更早的时候做类似的事情?另外,Kotlin的语法糖也可能吗?主要是人的例子:
val adam = Person("Adam").apply {
age = 20 // same as this.age = 20 or adam.age = 20
city = "London"
}编辑1:
我不知道我的问题是否那么清楚,所以我会用Rust的地图给出一个例子。
这就是地图是如何在锈蚀中完成的:
let newVector = myVector.iter().map(|x|, x * 2)这是如何在C++中完成的
std::string s("hello");
std::vector<std::size_t> ordinals;
std::transform(s.begin(), s.end(), std::back_inserter(ordinals),
[](unsigned char c) -> std::size_t { return c; });这要详细得多。
我想添加一些语法糖来做这样的事情:
std::string s("hello");
auto ordinals = my_ns::map(s,[](unsigned char c) -> std::size_t { return c; });my_ns::map的实现可以是这样的(我相信这是行不通的,它只是为了展示它是如何实现的)
template<typename T, U>
map(T t, std::function<U> f)
{
std::vector<U> ordinals;
std::transform(t.begin(), t.end(), std::back_inserter(ordinals),
[](U c) -> f(c));
return ordinals;
}在这种情况下,ordinals不需要是std::vector<std::size_t>类型,它可以是具有std::vector<T>转换的map类型。类型映射的原因是能够将函数链接起来,例如,使用map来减少。
原始问题
注意:这只是一个个人项目,我不打算使用它在生产或在大多数时候使用C++。
最近我使用了大量的Kotlin,我对Rust有点兴趣,我喜欢他们更高层次的功能。这让我想知道,我能创造一些语法糖来模仿这些特性吗?
我会试图模仿的一些东西(只是一个例子)
锈图:
let newVector = myVector.iter().map(|x|, x * 2)科特林
val adam = Person("Adam").apply {
age = 20 // same as this.age = 20 or adam.age = 20
city = "London"
}
val str = "Hello"
str.let {
println("The string's length is ${it.length}")
}我不打算使用完全相同的语法,但我想知道是否可以这样做:
int[] arr = {1, 2, 3};
auto d_arr = map(arr, [](int x){return x*2}) // maybe return a map type to be able to use .reduce, etc第一个kotlin让我不知道怎么做,但是第二个也可以用lambdas来解决。
我正在考虑使用新的类型,并创建到std::向量和数组的转换,这是C#的LINQ的工作方式之一。
任何关于如何做到这一点的建议都是值得赞赏的。
Ps:我知道std::transform和其他函数(我可能会在实现这些函数时使用它们),但是我想要一个比提供的API更简单的API(而且我也认为这是一个很好的个人项目)。
发布于 2022-02-08 03:12:28
您的示例可以很容易地更改为工作C++代码:
template <typename T, typename Fun> auto map(T t, Fun f) {
std::vector<typename T::value_type> ordinals;
std::transform(t.begin(), t.end(), std::back_inserter(ordinals), f);
return ordinals;
}这既不是非常惯用的,也不是对性能进行优化的,但它是有效的。(预先调整矢量的大小,而不是使用std::back_inserter,通过引用传递t,从而大大提高性能。)
编辑:您可以按以下方式添加reduce:
template <typename T, typename R, typename Fun> auto reduce(T t, R init, Fun f) {
return std::transform(t.begin(), t.end(), init, f);
}然后将它们结合起来:reduce(map(x, [](auto a) {...}), 0, [](int& a, auto b) {...})
显而易见的警告是:这将是非常缓慢的。这些函数学习模板概念很有趣,但在实践中,范围或旧风格的std::reduce/.会快得多。
编辑2:如果您想使用map作为成员函数,只需创建一个包装类:
template<class T>
struct Wrapper {
T d;
template <typename Fun> auto map(Fun f) {
std::vector<typename T::value_type> ordinals;
std::transform(d.begin(), d.end(), std::back_inserter(ordinals), f);
return wrap(ordinals);
}
template <typename R, typename Fun> auto reduce(R init, Fun f) {
return wrap(std::transform(d.begin(), d.end(), init, f));
}
};
template<class T> Wrapper<T> wrap(const T& t) { return {t}; }
template<class T> Wrapper<T> wrap(T&& t) { return {t}; }然后你就可以做wrap(my_vec).map(...).reduce(..., ...)了
for循环在这里会更快,因为您正在进行大量不必要的复制:您不必要地在map中创建一个新向量并多次复制数据(std::back_inserter,按值传递)。
发布于 2022-02-08 03:10:53
我想知道是否可以这样做:
int[] arr = {1,2,3};d_arr = map(arr,int x{返回x*2})
在C++标准库中,这个意义上的"map“称为"transform”。一个有用的例子:
auto double_ = [](auto x){ return x*2; }; // you may also use a normal function
auto doubled_view = std::views::all(arr)
| std::views::transform(double_);可以用地图链接像reduce这样的函数。
你可以缩小范围。不幸的是,C++20标准范围并没有提供一个约简函数,因此必须使用另一个范围实现,或者使用基于迭代器的函数。后一种情况的例子:
auto sum = std::reduce(
std::execution::unseq, // optional execution policy
doubled_view.begin(),
doubled_view.end(),
0
// you can use a functor to do something other than add
);到std::向量的转换
还可以从范围内创建容器:
std::vector doubled_vector(
doubled_view.begin(), doubled_view.end());请注意,为范围视图的中间阶段创建容器可能会带来不必要的开销。
https://stackoverflow.com/questions/71027960
复制相似问题