diff --git a/CMakeLists.txt b/CMakeLists.txt index 9948b84..79cf91a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ set(PROJECT_NAME_TEST ${PROJECT_NAME}_unit_test) # name for the unit-test execut # Compiler and language configuration # ---------------------------------------------------------------------------------------- # Require C++17 for GoogleTest and modern C++ features -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Optionally enforce warnings (good for learning/debugging) @@ -124,6 +124,8 @@ set(APP_SOURCES "src/core/datatypes/container/sequence/Array.cpp" "src/core/datatypes/container/sequence/Vector.cpp" "src/core/datatypes/container/unordered/UnorderedMap.cpp" + "src/core/expression/Lambda.cpp" + "src/core/expression/FunctionPointer.cpp" ) # Test files diff --git a/src/core/expression/FunctionPointer.cpp b/src/core/expression/FunctionPointer.cpp new file mode 100644 index 0000000..800af7d --- /dev/null +++ b/src/core/expression/FunctionPointer.cpp @@ -0,0 +1,61 @@ +#include +#include +#include + +namespace { + +int increase(int a, int b) { + return a > b; +} + +int decrease(int a, int b) { + return a < b; +} + +// // Function +// // Declaring +// return_type (*FuncPtr) (parameter type, ....); +typedef int (*SortFcn)(int a, int b); + +void run() { + std::vector vect{1, 6, 4, 22, 0, 6, 33, 39, -5}; + + auto f_print = [](const std::vector& vec) { + for (const auto& e : vec) { + std::cout << e << " "; + } + std::cout << "\n"; + }; + + std::cout << "Before sorting : \n"; + f_print(vect); + + std::cout << "Sorting in descending " + << "order \n"; + + // Use auto + auto sortTypeAuto = increase; + std::sort(vect.begin(), vect.end(), sortTypeAuto); + + // Use pointer + SortFcn sortTypePtr = decrease; + f_print(vect); + + std::cout << "Sorting with absolute " + << "value as parameter\n "; + std::sort(vect.begin(), vect.end(), sortTypePtr); + + for (auto i : vect) + std::cout << i << " "; + std::cout << "\n"; +} +} // namespace + +struct FunctionPointer { + FunctionPointer() { + std::cout << "\n--- Function Pointer Example ---\n"; + run(); + } +}; + +static FunctionPointer autoRunner; diff --git a/src/core/expression/Lambda.cpp b/src/core/expression/Lambda.cpp new file mode 100644 index 0000000..0887de2 --- /dev/null +++ b/src/core/expression/Lambda.cpp @@ -0,0 +1,48 @@ +#include // for std::sort +// std::sort +// default (1) +// template void sort (RandomAccessIterator first, RandomAccessIterator last); +// custom (2) +// template void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp); + +#include +#include + +namespace { +void run() { + std::vector vect{-1, -6, 4, 2, 0, 6, 3, 9, -5}; + + auto f_print = [](const std::vector& vec) { + for (const auto& e : vec) { + std::cout << e << " "; + } + std::cout << "\n"; + }; + + std::cout << "Before sorting : \n"; + f_print(vect); + + std::cout << "Sorting in descending " + << "order \n"; + std::sort(vect.begin(), vect.end(), [](int a, int b) { return a > b; }); + + f_print(vect); + + std::cout << "Sorting with absolute " + << "value as parameter\n "; + std::sort(vect.begin(), vect.end(), [](int a, int b) { return a < b; }); + + for (auto i : vect) + std::cout << i << " "; + std::cout << "\n"; +} +} // namespace + +struct LambdaRunner { + LambdaRunner() { + std::cout << "\n--- Lambda Expression Example ---\n"; + run(); + } +}; + +static LambdaRunner autoRunner; diff --git a/src/core/expression/README.md b/src/core/expression/README.md new file mode 100644 index 0000000..7f443f9 --- /dev/null +++ b/src/core/expression/README.md @@ -0,0 +1,84 @@ +# Theory + +## 1. Lambda Expressions +- In C++11 and later, lambda is a convenient way of defining an anonymous function object right at the location where it's involked or passed as an argument to a function. + +- Syntax: +```cpp +[=] () mutable throw() -> int +{ + int n = x + y; + return n; +} + +``` +- `[=]`: capture clause a.k.a lambda introducer +- `()`: (O) pararam list a.k.a lambda declarator +- `mutable`: (O) +- `throw()`: (O) +- `-> int`: (O) trailing-return-type +- body + +### 1.1 Capture Clause +- It uses to introduce new variables in its body, specifics which vars are captured, and whether the capture is `by value[=]` or `by reference [&]`. +- An empty capture clause `[]` indicates that the body accesses no vars in the enclosing scope. +- An identifier or `this` cannot appear more than once in a capture scope. +- Since C++14, we can introduce and initialize new vars in the capture scope. +- E.g. +```cpp +int a{}; +int b{}; + +auto f = []{ // no capture + return 1; +} + +auto f0 = [a]{ // capture by value + return a+1; +} + +auto f1 = [&a]{ + return a+=1; // capture by reference (a = 1) +} + +auto f2 = [=]{ + return a + b; // all capture by value +} + +auto f3 = [&]{ + a+=1; + b+=1; + return a + b; // all capture by reference +} + +auto f4 = [int a{}]{ // no capture + return a; +} +``` + +## 2. Function Pointers +- A function pointer is a pointer variable that stores the address of a function with a specific return type and parameter list. +- Syntax: +```cpp +// Declare +return_type (*FuncPtr) (parameter type, ....); + +// Referencing: Assigning a function’s address to the function pointer. +FuncPtr = function_name; + +// 3) Dereferencing: Invoking the function using the pointer. The dereference operator * is optional during function calls. +FuncPtr(10, 20); // Preferred +(*FuncPtr)(10, 20); // Also valid +``` + +- e.g. +```cpp +void print(int a){ + std::cout << a; +} + +void (*FuncPtr)(int a); +FuncPtr = print; +FuncPtr(1); +``` + diff --git a/src/main.cpp b/src/main.cpp index d6f9f84..abcc68a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,22 @@ #include "version.h" int main(int argc, char* argv[]) { + std::cout << std::endl; + if (__cplusplus == 202302L) + std::cout << "C++23"; + else if (__cplusplus == 202002L) + std::cout << "C++20"; + else if (__cplusplus == 201703L) + std::cout << "C++17"; + else if (__cplusplus == 201402L) + std::cout << "C++14"; + else if (__cplusplus == 201103L) + std::cout << "C++11"; + else if (__cplusplus == 199711L) + std::cout << "C++98"; + else + std::cout << "pre-standard C++ or an unknown version: " << __cplusplus; + std::cout << "\n"; std::cout << APP_NAME << " v" << APP_VERSION << std::endl; std::cout << APP_DESCRIPTION << std::endl; return 0;