Part 7 - function signatures
In this part I'll visit function signatures and describe what types your arguments should have.
It's always better to look at an example. Let's say we have a function that will say if red is dominant color in pixel from position x and y on screen.
bool is_red(int x, int y);
bool is_red(int& x, int& y);
bool is_red(const int& x, const int& y);
bool is_red(int* x, int* y);
bool is_red(const int* x, const int* y);
void is_red(int x, int y, bool& result);
// I could go on and on...
But we have to begin somewhere.
return type
In C it's common for functions to return data via function arguments.
bool do_something(int arg1, int& value);
// returned bool is actually saying if function succeeded or not
// returned value is stored in "value" argument
This is due to pathetic limitations of C. In C++ we don't have to do such things due to std::tuple deconstruction. This concludes that our function should return what we want to return => bool.
One may ask: "what if I want to return optional?" And that is a very good question. You can wrap your return type in std::optional. However, std::expected is soon to be added (as of writing this article) and provides even better way of returning optional values, because it allows to provide a "reason why call failed" well. It can easily be added to your project by using github.com/TartanLlama/expected.
auto optional_return(const bool& arg) {
return arg ? std::optional<std::string>{"Value"} : std::nullopt;
}
argument types
Assuming we plan to pass object of type T as our argument, we can pass it as:
T- "performs a copy and pass copied object to function" This will become costly if you attempt to copy e.g. png texture.const T- "performs a copy, but now you can't modify the object." Why would you ever do this?T*- "optional parameter, that will modify (object) inside of function". If you plan to modify the pointer itself, you have to remember, that you get a copy.const T*- "optional parameter, will not modify (object)" Here, your compiler is allowed to optimize away the copy, which means it will pass exactly the same pointer (without any copies).T&- "required parameter, will modify (object)"const T&- "required parameter, will not modify (object)" Just as withconst T*compiler is allowed to optimize away additional copies.T&&- "you have been granted full ownership of this argument"const T&&- just why?
summing up
-
returning or argument?-
returning-
return can fail?-
YES -
NO-
T
-
-
-
-
argument-
passing ownership?-
YES-
T&&
-
-
NO-
is it mandatory?-
YES-
need to mutate?-
YES-
T&
-
-
NO-
const T&
-
-
-
-
NO
const T* -
-
-
-
-
(Yes, this whole graf is done using CSS only)