Skip to content
/ funcpp Public

A collection of tools to facilitate expressive (maybe even functional) programming. Written in C++17

License

Notifications You must be signed in to change notification settings

geo-ant/funcpp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

func++

This, at some point in time, will be a collection of tools to facilitate expressive programming in C++. Written in C++17 and inspired by the ideas of functional programming. It consists of the following subprojects (more to come hopefully).

A Pipe Syntax for Optionals

Include the header optional_pipe.hpp for a pipe (|) operator that facilitates applying transformations to values of type std::optional<T>. The pipe operator takes an optional as the left hand argument and a callable with signature F:TU. It then returns the result of the transformation as a value of type std::optional<U>. If the initial optional was empty, then the returned optional is also empty, otherwise it contains the transformed value. The operator can be chained and also accepts callables returning void. Those are applied if the given optionals are not empty purely for their side effects. None of the callables may mutate the values inside the optional.

Example code

std::optional<std::string> optstr = std::string("Hello Optional World");

auto print_to_console = [](const auto & something)
                        {
                          cout << something<< endl;
                        };

auto square = [](const auto & val){return val*val;};

std::optional<size_t> length = optstr
                               | print_to_console
                               | &std::string::size
                               | print_to_console
                               | square
                               | print_to_console;

cout << "Length is " << length.value_or(0) << endl;

The code will output the following:

Hello Optional World
20
400
Length is 400

Further Reading

If you are curious, you can read about the implementation on my blog. Here is a good place to start. In the last part of the series I also describe some limitations of the implementation.

If Expressions to Replace Nested Ternary Operators

Located in the if_expressions.hpp header is an If-Then-ElseIf-Else syntax for expressively initializing variables depending on a condition. They can be used to replace nested ternary operators and make initialization code more readable.

Example Code

Include the header and pull the If class in scope by writing using funcpp::If. Then you can write

using funcpp::If;
int x = ... //some value
int sign_of_x = If(x>0).Then(1).ElseIf(x==0).Then(0).Else(-1);

This behaves as you would expect, depending on the condition. You can have as many ElseIf(condition).Then(value) expressions as you like (or none at all). The most bare-bones usage is just If(condition).Then(value).Else(alternative_value).

If the conditions and values are constexpr, then the whole expression can be evauluated at compile time with no runtime penalty. This makes it suitable for e.g. template value arguments.

In case you need to specify the object type (e.g. when initializing a string) you have to be explicit about the type in the first Then clause:

using funcpp::If;
bool is_french = ... // some value
std::string greeting    = If(is_french).Then(std::string("Bon Jour")).Else("Hello");
//or equivalent:
std::string salutation  = If(is_french).Then<std::string>("Bon Jour").Else("Hello");

Further Reading

You can read about the implementation, more details, and some caveats on my blog here.

Compile Time If Expressions for Conditionally Selecting Types

Located in the header type_selector.hpp, this expands the idea of the if expressions above and makes a similar syntax available to conditionally select types at compile time. While the standard library std::conditional metafunction only allows us to perform a simple if-else logic, the type selection metafunctions allow for more complicated logic while still giving us a readable syntax.

Example Code

We can use the metafunctions like so:

using funcpp::type::If;
constexpr int BIT_COUNT = /* some value */;
using IntType = If<(BIT_COUNT <= 8)>
                ::Then<uint8_t>
                ::ElseIf<(BIT_COUNT <= 16)>
                ::Then<uint16_t>
                ::ElseIf<(BIT_COUNT <= 32)>
                ::Then<uint32_t>
                ::Else<uint64_t>;
static_assert(std::is_same<IntType,uint16_t>::value);

Note that funcpp::type::If is different than funcpp::If because the former is a metafunction that operates on _types. We can use the funcpp::If at compile time as well, but only for constexpr values, not types.

Further Reading

You can read more about the implementation in the corresponding article on my dev blog.

About

A collection of tools to facilitate expressive (maybe even functional) programming. Written in C++17

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published