Baduit / Unic

A library to simulate the "unified call syntax" in C++20

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unic

A library to simulate the "unified call syntax" in C++20 with a slightly different syntax.

The goal behind this library is to mess around with this concept, it is not intented to be used in a serious project.

What is the "unified call syntax" ?

It is a way to call a free a similar way you would call a method. More information here :

What can I do with this library ?

// You can write something like this
str->*split(",");
// Instead of something like that
split(str, ",");

How to use it ?

Here's an example :

#include <iostream>
#include <vector>
#include <algorithm>

#include <unic/unic.hpp>


int main()
{
	using unic::operator->*;
	constexpr auto find = UNIC_GENERATE_PROXY(std::ranges::find);
	std::vector ints = { 1, 2, 3, 4, 5 };

	auto it = ints->*find(3);
	if (it != ints.cend())
		std::cout << "Found : " << *it << std::endl;
	else
		std::cout << "Not found :'(" << std::endl;
}

How to integrate it ?

It is a header only library, you can use it by:

  • Use CMake and link against it : target_link_libraries(your_target Croissant) (It is defined as an INTERFACE library)
  • Add in your project the single header Croissant.hpp which is in the folder single_header
  • Add the lib directory in your path and include <unic/unic.hpp>

How does it work ?

In this library there is only 2 small things :

  • An overload of the operator ->*, on the left side it takes anything and on the right side it takes a callable which take the object on the left side as argument.
  • A macro to create a proxy for a function so it can be used with the operator ->*, I will explain later why

Let's take the following code from the example:

using unic::operator->*; // 1
constexpr auto find = UNIC_GENERATE_PROXY(std::ranges::find); // 2
std::vector ints = { 1, 2, 3, 4, 5 };

ints->*find(3); // 3

First we make the overload of the operator->* avaible in the current scope.
Second we generate the proxy for the function from the standard library std::ranges::find

Now let's look at the last line see what is happening :

  • The operator() of find is called first because of the precedence of operator, it returns a lambda. This lambda has one argument which can be anything and when the lambda is called, it executes the wrapped function std::ranges::find, the first argument passed to std::ranges::find is the argument of the lambda, the others are the one passed to the operator() we just called, in our case 3.
  • The operator->* is called, on the left side there is the std::vector : ints, on the right side a lambda, it will call the lambda with ints as argument, this mean it is going to call std::ranges::find with ints and 3 as argument.

To summarize,

ints->*find(3)

Is equivalent to this :

unic::operator->*(ints, find.operator()(3));

And this is equivalent to that:

unic::operator->*(ints, [](auto&& t) { return std::ranges::find(std::forward<T>(t), 3; };);

Which is also also the equivalent of this:

std::ranges::find(ints, 3);

About

A library to simulate the "unified call syntax" in C++20

License:MIT License


Languages

Language:CMake 93.7%Language:C++ 5.8%Language:Shell 0.4%Language:Batchfile 0.2%