[英]Adding syntactic sugar to C++
新編輯:看起來 C++20 有一個新的范圍庫,從功能的角度來看,它可以滿足我的要求。 如何在 C++17 或更早的時間完成類似的事情? 另外, Kotlin 語法糖可能嗎? 主要是人的例子:
val adam = Person("Adam").apply {
age = 20 // same as this.age = 20 or adam.age = 20
city = "London"
}
我不知道我的問題是否那么清楚,所以我將使用 Rust 的 map 舉個例子。
這是在 rust 中完成 map 的方式:
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>
類型,它可以是map
類型,它具有std::vector<T>
的轉換。 類型 map 的原因是能夠將 reduce 等函數與 map 鏈接起來。
注意:這僅適用於個人項目,我不打算在生產中或大部分時間使用 C++ 時使用它。
我最近一直在使用很多 Kotlin,我正在涉足 Rust,我喜歡它們的高級功能。 這讓我想知道,我可以創建一些語法糖來模擬其中的一些功能嗎?
我會嘗試模仿的一些東西(只是一個例子)
Rust map:
let newVector = myVector.iter().map(|x|, x * 2)
Kotlin 讓
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 讓我不知道該怎么做,但第二個也可以使用 lambda 來解決。
我正在考慮使用新類型並創建到 std::vector 和 arrays 的轉換,類似於 C# 的 LINQ 的工作方式。
任何有關如何執行此操作的提示都將受到贊賞。
Ps:我知道 std::transform 和其他功能(我可能會在實現時使用它們),但我想要一個比提供的更簡單的 API (我也認為這將是一個不錯的個人項目) .
您的示例可以很容易地更改為工作 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
作為成員 function,只需制作一個包裝器 class:
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
,按值傳遞)。
我想知道是否可以做類似的事情:
int[] arr = {1, 2, 3}; auto d_arr = map(arr, [](int x){return x*2})
這個意義上的“地圖”在C++標准庫中被稱為“變換”。 一個工作示例:
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 等函數與 map 鏈接起來。
您可以縮小范圍。 不幸的是,C++20 標准范圍沒有附帶 reduce function,因此必須使用范圍的另一種實現,或者改用基於迭代器的函數。 后者的例子:
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::vector
您還可以從范圍創建容器:
std::vector doubled_vector(
doubled_view.begin(), doubled_view.end());
請注意,為范圍視圖的中間階段創建容器可能會產生不必要的開銷。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.