Skip to content

Commit 970c1c1

Browse files
committed
callable updated
1 parent e544a50 commit 970c1c1

8 files changed

+299
-504
lines changed

CMakeLists.txt

Lines changed: 114 additions & 138 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ read more [here](https://ros-developer.com/2017/11/08/docker/)
5656
* [Assert](docs/assert.md)
5757
* [Atomic operations and Types](docs/atomic.md)
5858
* [Attribute [[ attribute-list ]] ](docs/attribute.md)
59-
* [Basic IO Operation, Streams, Reading/Writing Files, Formating Output, cin, scanf, gets, getline, printf](docs/basic_IO_operation.md)
59+
* [Basic IO Operation, Streams, Reading/Writing Files, Formatting Output, cin, scanf, gets, getline, printf](docs/basic_IO_operation.md)
6060
* [Bitset, Bit field, Bitwise Operations](docs/bitset_bit_field_bitwise_operations.md)
61-
* [Callbacks, Callable Objects, std::function, std::bind, std::invoke, Lambda](docs/callbacks.md)
61+
* [Callbacks](docs/callbacks.md)
62+
* [Callable Objects, std::function, std::bind, Lambda](docs/callable_objects_function_bind_lambda.md)
6263
* [Clock, Date, Time](docs/date_time.md)
6364
* [Conditional Compilation](src/conditional_compilation.cpp)
6465
* [Containers](docs/containers.md)
@@ -83,6 +84,7 @@ read more [here](https://ros-developer.com/2017/11/08/docker/)
8384
* [Functions, Extern Function, Function Objects, Function Pointer, Inline Functions](docs/functions.md)
8485
* [Hash](src/hash.cpp)
8586
* [Heap and Stack, Memory Layout of C Programs](docs/heap_and_stack_memory_layout_of_C_programs.md)
87+
* [Invoke](docs/std_invoke.md)
8688
* [Iterator, for_each loop, range-for loop, Loop optimization](docs/iterator_loop.md)
8789
* [Lambda](docs/lambda.md)
8890
* [Literals](docs/literals.md)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Callable object
2+
In C++, a callable object is an object that can be invoked like a function. Callable objects can be used in a variety of ways, including as function objects, function pointers, and lambdas.
3+
4+
There are several types of callable objects in C++, including:
5+
6+
1. Function pointers: These are pointers that point to functions. They can be used to call the function that they point to.
7+
8+
2. Function objects: These are objects that behave like functions. They implement the function call operator, operator(), and can be invoked like functions.
9+
10+
3. Lambda expressions: These are anonymous functions that can be defined inline. They can capture variables from their enclosing scope and can be used as function objects.
11+
12+
4. Member function pointers: These are pointers that point to member functions of a class. They can be used to call the member function that they point to.
13+
14+
5. Function references: These are references to functions. They can be used to call the function that they refer to.
15+
16+
Callable objects provide a lot of flexibility and can be used in many different situations, from implementing algorithms to passing functions as arguments to other functions.
17+
18+
19+
20+
#Partial application
21+
In computer science, partial function application refers to the process of fixing a number of arguments to a function,
22+
23+
The C++ standard library provides `bind(function, args..)` to return a function object that is the result of partial application of the given arguments to the given function. Alternatively, lambda expressions can be used.
24+
25+
## std::bind
26+
27+
Refs: [1](https://www.youtube.com/watch?v=ZlHi8txU4aQ), [2](https://stackoverflow.com/questions/6610046/stdfunction-and-stdbind-what-are-they-and-when-should-they-be-used), [3](https://en.wikipedia.org/wiki/Partial_application)
28+
29+
[code](../src/bind.cpp)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
`std::invoke` is a generic way to activate any callable. `std::invoke` takes something callable, and arguments to call it with, and does the call. `std::invoke( f, args... )` is a slight generalization of typing `f(args...)` that also handles a few additional cases.
3+
4+
5+
6+
## std::bind
7+
8+
Refs: [1](https://www.youtube.com/watch?v=ZlHi8txU4aQ)
9+
10+
[code](../src/bind.cpp)

docs/callbacks.md

Lines changed: 42 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,74 @@
1-
- [Callbacks](#callbacks)
2-
* [Function pointers (including pointers to member functions)](#function-pointers--including-pointers-to-member-functions-)
3-
* [std::function](#std--function)
4-
* [Lambda expressions](#lambda-expressions)
5-
* [Bind expressions](#bind-expressions)
6-
* [Function objects (classes with overloaded function call operator operator())](#function-objects--classes-with-overloaded-function-call-operator-operator---)
7-
- [Sending a function as parameter to an other function](#sending-a-function-as-parameter-to-an-other-function)
8-
9-
101
# Callbacks
112

12-
A callback is a callable accepted by a class or function, used to customize the current logic depending on that callback. `std::invoke` is a generic way to activate any callable. `std::invoke` takes something callable, and arguments to call it with, and does the call. `std::invoke( f, args... )` is a slight generalization of typing `f(args...)` that also handles a few additional cases.
13-
14-
## Function pointers (including pointers to member functions)
15-
## std::function
16-
Class template std::function is a general-purpose polymorphic function wrapper. Instances of std::function can store, copy, and invoke any Callable target:
17-
1. functions
18-
2. lambda expressions
19-
3. bind expressions
20-
4. functors
3+
A callback function is a callable passed as an argument to a class or function, used to customize the current logic depending on that callback.
4+
For instance imagine you have a class for modeling a robot and you want to give this freedom to user to define and use different motion planner. You can ask the user to pass the solver function to the robot class so the robot class use that one for moving around.
215

226
```cpp
23-
void print(int value)
24-
{
25-
std::cout<< value<<std::endl;
26-
}
27-
```
7+
typedef std::function<std::vector<double>(double, double)> CallbackFunction;
288

29-
storing a functions:
30-
```cpp
31-
std::function<void(int)> funcPrint=print;
32-
funcPrint(3);
33-
```
9+
class robot {
3410

35-
store a bind expressions:
11+
public:
12+
CallbackFunction m_callback;
3613

37-
```cpp
38-
std::function<void (int)> funcPrint=std::bind(&print,std::placeholders::_1);
39-
std::function<void (int)> f(funcPrint);
40-
f(3);
41-
```
14+
void makeMotion(std::vector<double> trajectory) {
15+
std::cout << "robot is traversing the generated trajectory:" << std::endl;
16+
for (const auto &p : trajectory)
17+
std::cout << p << std::endl;
18+
}
4219

43-
store lambda expressions:
44-
```cpp
45-
auto lambda=[](int value){std::cout<< value<<std::endl;};
46-
std::function<void(int)>f(lambda);
47-
f(3);
48-
```
20+
void move(double start, double goal) {
4921

50-
store a functors:
51-
```cpp
52-
void (*printfunctor)(int);
53-
printfunctor=print;
54-
std::function<void(int)>f(printfunctor);
55-
f(3);
22+
std::vector<double> trajectory = m_callback(start, goal);
23+
makeMotion(trajectory);
24+
}
25+
};
5626
```
5727
58-
## Lambda expressions
59-
## Bind expressions
60-
`std::bind` works as a Functional Adaptor i.e. it takes a function as input and returns a new function Object as an output with with one or more of the arguments of passed function bound or rearranged (partial function application).
28+
Now we can have different solvers:
6129
62-
first example:
6330
```cpp
64-
void print(int firstParam, int secondParam)
65-
{
66-
std::cout << "First Param is: " << firstParam << " Second Param is: " << secondParam << std::endl;
31+
std::vector<double> planer1(double start, double goal) {
32+
return {start, (start + goal) / 2, goal};
33+
}
34+
std::vector<double> planer2(double start, double goal) {
35+
return {start, start + (start + goal) / 3, 2 * (start + goal) / 3, goal};
6736
}
6837
```
69-
in the main:
38+
Now we can assign and use different solvers:
39+
7040
```cpp
71-
int firstParam=3;
72-
int secondParam=5;
73-
auto MyPrinter=std::bind(&print,firstParam,secondParam);
74-
MyPrinter();
41+
robot myrobot1;
42+
myrobot1.m_callback = planer1;
43+
myrobot1.move(start, goal);
7544
```
76-
You can use `std::placeholders::_` to set the order of the parameters:
45+
46+
or
7747

7848
```cpp
79-
auto reversePrintFunc = std::bind(&print, std::placeholders::_2, std::placeholders::_1);
80-
81-
int firstParam = 3;
82-
int secondParam = 5;
83-
84-
print(firstParam, secondParam);
85-
reversePrintFunc(firstParam, secondParam);
49+
std::function<std::vector<double>(double, double)> planer2_ptr =
50+
std::bind(&planer2, std::placeholders::_1, std::placeholders::_2);
8651

52+
myrobot1.m_callback = planer2_ptr;
53+
myrobot1.move(start, goal);
8754
```
88-
You can use it like a lambda expression:
8955
56+
or
9057
9158
```cpp
92-
std::vector<int> vec={1,2,3};
93-
std::vector<int> values(vec.size(),0);
94-
95-
// raise every value in vec to the power of 3
96-
auto f=std::bind(&std::pow<int,int>,std::placeholders::_1,3);
97-
std::transform(vec.begin(), vec.end(), values.begin(), f);
98-
99-
for(auto value:values)
100-
std::cout<< value<<std::endl;
101-
```
102-
an other example:
59+
auto planer_lambda = [](double start, double goal) {
60+
return std::vector<double>(10, 2);
61+
};
10362
104-
```cpp
105-
int param=3;
106-
auto printer=std::bind(&printTemplate<int>,param);
63+
myrobot1.m_callback = planer_lambda;
64+
myrobot1.move(start, goal);
10765
```
108-
or
109-
```cpp
110-
auto printer=std::bind(&printTemplate<int>,std::placeholders::_1);
111-
```
112-
an calling it:
113-
```cpp
114-
std::function<void (int)>f(printer);
115-
f(param);
116-
```
117-
118-
119-
Refs: [1](//https://www.youtube.com/watch?v=ZlHi8txU4aQ)
66+
[code](../src/callbacks.cpp)
12067

121-
[code](../src/bind.cpp)
68+
12269

70+
Refs: [1](https://stackoverflow.com/questions/2298242/callback-functions-in-c)
12371

124-
Refs: [1](https://stackoverflow.com/questions/2298242/callback-functions-in-c), [2](https://stackoverflow.com/questions/6610046/stdfunction-and-stdbind-what-are-they-and-when-should-they-be-used), [2](https://en.wikipedia.org/wiki/Partial_application)
125-
[source code](../src/callbacks.cpp)
12672

12773

12874

docs/std_invoke.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
## std::invoke
2+
`std::invoke` is a generic way to activate any callable. `std::invoke` takes something callable, and arguments to call it with, and does the call. `std::invoke( f, args... )` is a slight generalization of typing `f(args...)` that also handles a few additional cases.
3+
4+
The advantage of using std::invoke over directly invoking a callable object is that it provides a uniform syntax that works for all callable objects. This means that you can use the same syntax to invoke a function pointer, member function, function object, or lambda, without needing to know the specific type or signature of the callable object.
5+
6+
7+
8+
```cpp
9+
void foo(int x) {
10+
std::cout << "foo(" << x << ")" << std::endl;
11+
}
12+
13+
struct bar {
14+
void operator()(int x) const {
15+
std::cout << "bar(" << x << ")" << std::endl;
16+
}
17+
};
18+
```
19+
now you can invoke them as followings:
20+
21+
22+
1. Invoke a function pointer:
23+
```cpp
24+
int x = 42;
25+
std::invoke(foo, x);
26+
```
27+
28+
2. Invoke a member function:
29+
```cpp
30+
bar b;
31+
std::invoke(&bar::operator(), b, x);
32+
```
33+
34+
3. Invoke a function object:
35+
```cpp
36+
std::invoke(std::function<void(int)>([](int x) { std::cout << "lambda(" << x << ")" << std::endl; }), x);
37+
````

0 commit comments

Comments
 (0)