'Adding syntactic sugar to C++

Edit 2:

New edit: it looks like C++20 has a new ranges library, which does what I want from the functional point of view. How would something similar be done on C++17 or earlier? Also, would the Kotlin syntactic sugar be possible? Mainly the person example:

val adam = Person("Adam").apply { 
    age = 20 // same as this.age = 20 or adam.age = 20
    city = "London"
}

Edit 1:

I don't know if my question was that clear, so I'll give an example using Rust's map.

This is how a map is done in rust:

let newVector = myVector.iter().map(|x|, x * 2)

This is how it is done in 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; });

This is a lot more verbose.

I'd like to add some syntactic sugar to do something like this instead:

std::string s("hello");
auto ordinals = my_ns::map(s,[](unsigned char c) -> std::size_t { return c; });

The implementation of my_ns::map could be something like this (I'm sure this will not work, it's just to show how it could be done)

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;
}

In this case ordinals doesn't need to be of type std::vector<std::size_t>, it could be of a type map which has a conversion for std::vector<T>. The reason for a type map is to be able to chain functions like reduce with map.

Original Question

Note: this is for a personal project only, I do not intend to use it in production or when working with C++ most of the time.

I have been using a lot of Kotlin lately and I'm dabbling a little with Rust and I love their higher level features. That got me wondering, can I create some syntactic sugar to emulate some of these features?

Some of the stuff I'd be trying to emulate(just an example)

Rust map:

let newVector = myVector.iter().map(|x|, x * 2)

Kotlin let

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}")
}

I do not plan on using the exact same syntax, but I'd like to know if it would be possible to do something like:

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

The first kotlin let example I wouldn't know how to do, but the second could be solved using lambdas as well.

I'm thinking of using new types and create conversions to std::vector and arrays, kind of how C#'s LINQ works.

Any tips on how to do this are appreciated.

Ps: I know about std::transform and other functions(I'd probably use them when implementing this), but I'd like a simpler API than the ones offered (and I also think that it would be a nice personal project).

c++


Solution 1:[1]

I'd like to know if it would be possible to do something like:

int[] arr = {1, 2, 3};
auto d_arr = map(arr, [](int x){return x*2})

"map" in this sense is called "transform" in C++ standard library. A working example:

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_);

to be able to chain functions like reduce with map.

You can reduce ranges. Unfortunately, the C++20 standard ranges don't come with a reduce function, so one has to use either another implementation of ranges, or use the iterator based functions instead. Example of latter:

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
     );

conversions to std::vector

You can also create containers from ranges:

std::vector doubled_vector(
    doubled_view.begin(), doubled_view.end());

Note that creating containers for intermediate stages of range views can have unnecessary overhead.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1