Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f6b1806
first commit for map
jkalias Sep 24, 2023
f51b304
StdMapConstructor
jkalias Sep 24, 2023
b6e9920
InitializerList ctor and is_empty()
jkalias Sep 24, 2023
e79df1c
access operator
jkalias Sep 24, 2023
d70521c
clear
jkalias Sep 24, 2023
12b4d80
contains
jkalias Sep 24, 2023
f16760e
removed some tests
jkalias Sep 24, 2023
fa44296
Finalized map implementation
jkalias Apr 19, 2026
73f7901
Update cmake.yml
jkalias Apr 19, 2026
88c8381
fixed strict comparator crash
jkalias Apr 19, 2026
223b54c
Merge branch 'main' into functional_map
jkalias Apr 19, 2026
93bc719
Revert "Merge branch 'main' into functional_map"
jkalias Apr 19, 2026
6e16038
Updated GoogleTest to V.1.17 and fixed CMake warnings/errors
jkalias May 2, 2026
0ef4931
revertred changes to optional
jkalias May 2, 2026
c750d76
reverted changes to set
jkalias May 2, 2026
54d2b33
reverted changes to vector
jkalias May 2, 2026
afabdc5
reverted changed to optional_test
jkalias May 2, 2026
363ebc0
reverted vector_test
jkalias May 2, 2026
68fb5b1
reverted .gitignore
jkalias May 2, 2026
f1ad966
Update CMakeLists.txt
jkalias May 2, 2026
1f5c819
CMakeLists to 3.10 and GoogleTests to 1.12.1
jkalias May 2, 2026
8746523
Update CMakeLists.txt
jkalias May 2, 2026
b2f1ca1
replaced std::less_equal with std::less (strict comparator)
jkalias May 2, 2026
df1df00
std::greater_equal (strict comparator)
jkalias May 2, 2026
62cd734
removed map_keys and map_values
jkalias May 2, 2026
6af2f08
comment
jkalias May 2, 2026
6f27389
Update README.md
jkalias May 2, 2026
9bf26f0
Update README.md
jkalias May 2, 2026
94abcf3
cleaned up documentation
jkalias May 2, 2026
4a44a28
docs update pass
jkalias May 2, 2026
7e37464
final docs pass
jkalias May 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.14)
project(functional_cpp VERSION 1.0)
if(POLICY CMP0135)
#set the timestamps of all extracted contents to the time of the extraction
cmake_policy(SET CMP0135 NEW)
endif()
project(functional_cpp VERSION 1.0.2)

# GoogleTest requires at least C++11
if(NOT "${CMAKE_CXX_STANDARD}")
Expand All @@ -16,7 +20,7 @@ endif()
include(FetchContent)
FetchContent_Declare(
googletest
Comment thread
jkalias marked this conversation as resolved.
URL https://github.com/google/googletest/archive/8d51ffdfab10b3fba636ae69bc03da4b54f8c235.zip
URL https://github.com/google/googletest/archive/refs/tags/release-1.12.1.zip
)
FetchContent_MakeAvailable(googletest)

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Ioannis Kaliakatsos
Copyright (c) 2026 Ioannis Kaliakatsos

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
121 changes: 115 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![CMake Build Matrix](https://github.com/jkalias/functional_cpp/actions/workflows/cmake.yml/badge.svg)](https://github.com/jkalias/functional_cpp/actions/workflows/cmake.yml)
[![GitHub license](https://img.shields.io/github/license/jkalias/functional_cpp)](https://github.com/jkalias/functional_cpp/blob/main/LICENSE)
# Say hello to functional C++
A wrapper for C++ std::vector and std::set geared towards functional programming and fluent APIs. This project is heavily influenced and inspired by C# and Swift.
A wrapper for the C++ workhorses std::vector, std::set and std::map geared towards functional programming and fluent APIs. This project is heavily influenced and inspired by C# and Swift.

The primary focus of this library is
* readability at the call site ("make it work, make it right, make it fast")
Expand Down Expand Up @@ -268,6 +268,8 @@ for_each_parallel
map_parallel
filter_parallel
sort_parallel
sort_ascending_parallel
sort_descending_parallel
all_of_parallel
any_of_parallel
none_of_parallel
Expand Down Expand Up @@ -310,7 +312,7 @@ const auto colleagues_but_not_friends = colleagues.difference_with(friends);
// find which friends are colleagues
// same as colleagues.intersect_with(friends)
// contains person(51, "George"), person(41, "Jackie")
const auto good_colleagues = friends.intersection_with(colleagues);
const auto good_colleagues = friends.intersect_with(colleagues);

// a set of close family members
const fcpp::set<person, person_comparator> family({
Expand All @@ -322,8 +324,8 @@ const fcpp::set<person, person_comparator> family({
// contains person(51, "George"), person(41, "Jackie"), person(42, "Crystal"), person(51, "Paul"), person(81, "Barbara")
const auto friends_and_family = friends.union_with(family);

// all set keys in a vetor
const fcpp::vector<person> = friends_and_family.keys();
// all set keys in a vector
const auto people = friends_and_family.keys();
```

### zip, map, filter, reduce
Expand Down Expand Up @@ -408,10 +410,10 @@ numbers.none_of([](const int& number) {

fcpp::set<int> numbers({1, 2, 3, 4, 5, 7, 8});

// numbers -> fcpp::set<int> numbers({1, 2, 3, 5, 7, 8});
// numbers -> fcpp::set<int>({1, 2, 3, 5, 7, 8});
numbers.remove(4);

// numbers -> fcpp::set<int> numbers({1, 2, 3, 5, 7, 8, 10});
// numbers -> fcpp::set<int>({1, 2, 3, 5, 7, 8, 10});
numbers.insert(10);

// returns true
Expand All @@ -426,3 +428,110 @@ numbers.size();
// removes all keys
numbers.clear();
```

## Functional map usage (fcpp::map)
### map_to, filter, reduce, for_each
```c++
#include "map.h" // instead of <map>

const fcpp::map<std::string, int> ages({
{"jake", 32},
{"mary", 16},
{"david", 40}
});

// keep only persons above 18 years old
const auto adults = ages
.filtered([](const std::pair<const std::string, int>& element) {
return element.second >= 18;
});

// ages_by_initial -> fcpp::map<char, std::string>({{'d', "40 years"}, {'j', "32 years"}})
const auto ages_by_initial = adults.map_to<char, std::string>([](const std::pair<const std::string, int>& element) {
return std::make_pair(element.first[0], std::to_string(element.second) + " years");
});

// total_age = 72
const auto total_age = adults.reduce(0, [](const int& partial_sum, const std::pair<const std::string, int>& element) {
return partial_sum + element.second;
});

/*
prints the following:
jake is 32 years old.
david is 40 years old.
*/
adults.for_each([](const std::pair<const std::string, int>& element) {
std::cout << element.first << " is " << element.second << " years old." << std::endl;
});
```

### all_of, any_of, none_of
```c++
#include "map.h" // instead of <map>

const fcpp::map<std::string, int> ages({
{"jake", 32},
{"mary", 26},
{"david", 40}
});

// returns true
ages.all_of([](const std::pair<const std::string, int>& element) {
return element.second > 20;
});

// returns false
ages.all_of([](const std::pair<const std::string, int>& element) {
return element.second < 35;
});

// returns true
ages.any_of([](const std::pair<const std::string, int>& element) {
return element.second == 40;
});

// returns false
ages.any_of([](const std::pair<const std::string, int>& element) {
return element.second > 50;
});

// returns true
ages.none_of([](const std::pair<const std::string, int>& element) {
return element.second < 18;
});

// returns false
ages.none_of([](const std::pair<const std::string, int>& element) {
return element.second == 26;
});
```

### keys, values, remove, insert
```c++
#include "map.h" // instead of <map>

fcpp::map<std::string, int> ages({
{"jake", 32},
{"mary", 26},
{"david", 40}
});

// names -> fcpp::vector<std::string>({"david", "jake", "mary"})
const auto names = ages.keys();

// years -> fcpp::vector<int>({40, 32, 26})
const auto years = ages.values();

// ages -> fcpp::map<std::string, int>({{"david", 40}, {"jake", 32}})
ages.remove("mary");

// ages -> fcpp::map<std::string, int>({{"anna", 28}, {"david", 40}, {"jake", 32}}), mary has already been removed
ages.insert("anna", 28);

// without_jake -> fcpp::map<std::string, int>({{"anna", 28}, {"david", 40}})
const auto without_jake = ages.removing("jake");

// with_paul -> fcpp::map<std::string, int>({{"anna", 28}, {"david", 40}, {"jake", 32}, {"paul", 51}})
const auto with_paul = ages.inserting("paul", 51);
```
2 changes: 1 addition & 1 deletion include/compatibility.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// MIT License
//
// Copyright (c) 2023 Ioannis Kaliakatsos
// Copyright (c) 2026 Ioannis Kaliakatsos
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
Expand Down
14 changes: 7 additions & 7 deletions include/export_def.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// MIT License
//
// Copyright (c) 2023 Ioannis Kaliakatsos
// Copyright (c) 2026 Ioannis Kaliakatsos
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
Expand All @@ -23,13 +23,13 @@
#pragma once

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#ifdef FUNCTIONAL_CPP_EXPORTS
#define FunctionalCppExport __declspec( dllexport )
#ifdef FUNCTIONAL_CPP_EXPORTS
#define FunctionalCppExport __declspec( dllexport )
#else
#define FunctionalCppExport __declspec( dllimport )
#endif
#else
#define FunctionalCppExport __declspec( dllimport )
#endif
#else
#define FunctionalCppExport __attribute__ ((__visibility__("default")))
#define FunctionalCppExport __attribute__ ((__visibility__("default")))
#endif

#include "compatibility.h"
112 changes: 56 additions & 56 deletions include/index_range.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// MIT License
//
// Copyright (c) 2023 Ioannis Kaliakatsos
// Copyright (c) 2026 Ioannis Kaliakatsos
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
Expand All @@ -26,60 +26,60 @@
// A struct used for container safe access based on index
struct FunctionalCppExport index_range
{
// Used for returning values of invalid operations
static index_range invalid;

// Create with start index and element count (end index is calculated)
static index_range start_count(int start, int count);

// Create with start and end index (count is calculated)
static index_range start_end(int start, int end);

// The start index of the index range
// example:
// [0] [1] [2] [3] [4] [5] [6]
// 5 3 9 1 8 3 2
// ^ ^
// | |
// start end
//
// start = 2
// end = 4
// count = 3
int start;

// The end index of the index range
// example:
// [0] [1] [2] [3] [4] [5] [6]
// 5 3 9 1 8 3 2
// ^ ^
// | |
// start end
//
// start = 2
// end = 4
// count = 3
int end;

// The total count of the elements in the index range
// example:
// [0] [1] [2] [3] [4] [5] [6]
// 5 3 9 1 8 3 2
// ^ ^
// | |
// start end
//
// start = 2
// end = 4
// count = 3
int count;

// Returns true if it's safe to use its contents
bool is_valid;

bool operator ==(const index_range& rhs) const;
bool operator !=(const index_range& rhs) const;

// Used for returning values of invalid operations
static index_range invalid;
// Create with start index and element count (end index is calculated)
static index_range start_count(int start, int count);
// Create with start and end index (count is calculated)
static index_range start_end(int start, int end);
// The start index of the index range
// example:
// [0] [1] [2] [3] [4] [5] [6]
// 5 3 9 1 8 3 2
// ^ ^
// | |
// start end
//
// start = 2
// end = 4
// count = 3
int start;
// The end index of the index range
// example:
// [0] [1] [2] [3] [4] [5] [6]
// 5 3 9 1 8 3 2
// ^ ^
// | |
// start end
//
// start = 2
// end = 4
// count = 3
int end;
// The total count of the elements in the index range
// example:
// [0] [1] [2] [3] [4] [5] [6]
// 5 3 9 1 8 3 2
// ^ ^
// | |
// start end
//
// start = 2
// end = 4
// count = 3
int count;
// Returns true if it's safe to use its contents
bool is_valid;
bool operator == (const index_range& rhs) const;
bool operator != (const index_range& rhs) const;
private:
index_range(int start, int count);
index_range(int start, int count);
};
Loading
Loading