I have been making various functions that will compute the sigma in a range of very specific functions. I am now trying to write a sigma function that you would input a lambda or a function and it would then calculate the sum of its outputs within a range. I have the iteration code done fine but now need to figure out how to input a lambda and call it inside that function.
here is my current code:
int sigma(int start, int end, ? function) {
if (start == end) {
return function(start);
}
else {
return function(start) + sigma(start + 1, end, function);
}
}
PS if anyone could help me make this not use recursion that would be amazing
You can make this function into a function-template:
template<typename Fn>
int sigma(int start, int end, Fn function) {
// ...
}
and then call it with a lambda:
auto lam = [](int) { return 42; };
std::cout << sigma(1, 5, lam);
To avoid the rescursion, the body could simply be:
int sum = 0;
for (int i = start; i <= end; ++i)
sum += function(i);
return sum;
You need the type for your parameter. So ask yourself what is this parameter supposed to be? Based upon your definition of sigma(), you appear to be expecting a function-like object that is invoked with an int parameter and returns an int. That is, a std::function<int(int)>. Your function's declaration might end up looking like the following.
int sigma(int start, int end, std::function<int(int)> & function);
If you want to handle functions with other signatures, then a function template might be more appropriate. See std::function vs template for a discussion.
Related
I'm trying to make a List class, mainly because there are some methods that aren't present for vectors that I'd like to implement myself. One of these is a map() function where you can pass in a lambda as a parameter and the method returns a new List in which each of the values in the old list was passed to the function.
The problem I'm having is with getting the method to deal with returning a List featuring a different type. For example:
List<Option<int>> y;
y.append(option(1));
y.append(option(2));
y.append(option(3));
//y is [Option(1), Option(2), Option(3)]
List<int> z = y.map([](Option<int> o) {return o.get();});
//z should be [1,2,3]
Where the map() function, in it's current state, is defined as:
template<typename S>
List<S> map(S (* function)(T)) {
List<S> output;
for (int i = 0; i < size(); i++) {
output.append(function((*this)[i]));
}
return output;
}
The problem is that the above doesn't seem to allow me to pass in a lambda, only a previously defined function, which defeats the purpose of convenience for the method. The only way I can get it to accept a lambda is by defining the function as:
template<typename S, typename R>
List<S> map(R function) {
List<S> output;
for (int i = 0; i < size(); i++) {
output.append(function((*this)[i]));
}
return output;
}
But this results in a different problem, where it says:
no instance of function template 'List<T>::map[with T=Option<int>]' matches the argument list
Is there a particular workaround for this, or will I have to declare functions for each time I call the map() function?
Use decltype. In your definition, you want to determine the type of the output list return value with what would be returned from the function. So you can do something like this:
template<typename R>
auto map(R function) {
List<std::decay_t<decltype(function(operator[](0)))>> output;
for(int i = 0; i < size(); i++) output.append(function(operator[](i)));
return output;
}
The type of the list elements is whatever function returns when called on the elements of this. The std::decay_t turns types you can't store (references, cv-qualified types, arrays, etc) into those you can (resp. non-references, none-qualified types, pointers, etc.).
A slightly more powerful result can be achieved with std::invoke_result, which lets you replace the function call with std::invoke:
template<typename T>
struct List { // Your list class, we need the T
template<typename R>
auto map(R function) {
List<std::decay_t<std::invoke_result_t<R, T&>>> output; // assuming that accesses give references
for(int i = 0; i < size(); i++) output.append(std::invoke(function, operator[](i)));
return output;
}
};
The result is that now you can also map things like pointers to members over your list.
Godbolt
In the following example, I would like a traverse method that receives a callback. This example works perfectly as soon as I don't capture anything [] because the lambda can be reduced into a function pointer. However, in this particular case, I would like to access sum.
struct Collection {
int array[10];
void traverse(void (*cb)(int &n)) {
for(int &i : array)
cb(i);
}
int sum() {
int sum = 0;
traverse([&](int &i) {
sum += i;
});
}
}
What is the proper way (without using any templates) to solve this? A solution is to use a typename template as follows. But in this case, you lack visibility on what traverse gives in each iteration (an int):
template <typename F>
void traverse(F cb) {
for(int &i : array)
cb(i);
}
Lambda types are unspecified; there is no way to name them.
So you have two options:
Make traverse a template (or have it take auto, which is effectively the same thing)
Fortunately this is a completely normal and commonplace thing to do.
Have traverse take a std::function<void(int)>. This incurs some overhead, but does at least mean the function need not be a template.
But in this case, you lack visibility on what traverse gives in each iteration (an int)
We don't tend to consider that a problem. I do understand that giving this in the function's type is more satisfying and clear, but generally a comment is sufficient, because if the callback doesn't provide an int, you'll get a compilation error anyway.
Only captureless lambdas can be used with function pointers. As every lambda definition has its own type you have to use a template parameter in all places where you accept lambdas which captures.
But in this case, you lack visibility on what traverse gives in each iteration (an int).
This can be checked easily by using SFINAE or even simpler by using concepts in C++20. And to make it another step simpler, you even do not need to define a concept and use it later, you can directly use an ad-hoc requirement as this ( this results in the double use of the requires keyword:
struct Collection {
int array[10];
template <typename F>
// check if F is "something" which can be called with an `int&` and returns void.
requires requires ( F f, int& i) { {f(i)} -> std::same_as<void>; }
void traverse(F cb)
{
for(int &i : array)
cb(i);
}
// alternatively you can use `std::invocable` from <concepts>
// check if F is "something" which can be called with an `int&`, no return type check
template <std::invocable<int&> F>
void traverse2(F cb)
{
for(int &i : array)
cb(i);
}
int sum() {
int sum = 0;
traverse([&](int &i) {
sum += i;
});
return sum;
}
};
In your case you have several ways of declaring a callback in C++:
Function pointer
void traverse(void (*cb)(int &n)) {
for(int &i : array)
cb(i);
}
This solution only supports types that can decay into a function pointer. As you mentioned, lambdas with captures would not make it.
Typename template
template <typename F>
void traverse(F cb) {
for(int &i : array)
cb(i);
}
It does accept anything, but as you noticed. the code is hard to read.
Standard Functions (C++11)
void traverse(std::function<const void(int &num)>cb) {
for(int &i : array)
cb(i);
}
This is the most versatile solution with a slightly overhead cost.
Don't forget to include <functional>.
This is part of a debugging assignment that I've been stuck on for days. I'm not as much looking for an answer as much as I'm looking for where to look to find the answer.
I have a function that takes an int as a parameter, and the test uses that function to calculate the sum of the range (0,n]. My problem is that I am new to C++ and have exhausted my knowledge of where to look to solve this. Any help would be greatly appreciated.
Also, it goes without saying that I cannot modify the test file.
Header.h
bool getNum(int n);
Header.cpp:
bool getNum(int n)
{
n = n + 1;
if (n < 10)
{
return true;
}
else
{
return false;
}
}
Test.cpp
int n = 0;
int sum = 0;
while (getNum(n) && n)
{
sum += n;
}
CHECK(sum == 45);
My problem is that I have no way of getting n to be true to pass the logical &&, so the test never visits the inside of the while loop.
You can change the value of an argument to a function, by taking that argument as a reference:
bool getNum(int &n) // note the reference parameter
{
// changes to n are visible to the caller of this function
}
You have to change the declaration of getNum to match as well, of course.
Note that there is no change to the calling code.
Here's a demo of a working example.
In embedded C/C++ programming is quite common to write for loops of this type:
...
for(int16_t i=0; i<5; i++)
{
if(true == unlockSIM(simPinNumber))
return true;
wait_ms(1000);
}
return false;
...
or like this while() loop:
bool CGps::waitGpsFix(int8_t fixVal)
{
int16_t iRunStatus=0, iFixStatus=0;
_timeWaitGpsFix = CSysTick::instance().set(TIME_TO_WAIT_GPS);
while(1)
{
bool bRet = _pGsm->GPSstatus(&iRunStatus, &iFixStatus);
if( (true == bRet) && (1 == iRunStatus) && (iFixStatus >= fixVal) )
return true;
if(CSysTick::instance().isElapsed(_timeWaitGpsFix))
return false;
wait_ms(500);
}
return false;
}
//---------------------------------------------------------------------------
is there any well known good pattern useful to don't write each time so many lines but just a function or method call?
For the for loop, you could use a function template that accepts the function (must return a boolean) and return when succeeded. For the while loop, things get more complicated, but I guess that lambdas could be used as true and false conditions.
For loop:
#include <iostream>
template<int retries, int wait_time, typename FUNC, typename ...Args>
bool retry(FUNC& f, Args &&... args)
{
for (int i = 0; i < retries; ++i)
{
if (f(std::forward<Args>(args)...)) return true;
if (i < retries - 1)
{
std::cout << "waiting " << wait_time << "\n";
}
}
return false;
}
bool func(int i)
{
return (i > 0);
}
bool func2(int i, int j)
{
return (i > j);
}
int main()
{
bool result = retry<5, 500>(func, 0);
std::cout << result << "\n";
result = retry<5, 500>(func, 1);
std::cout << result << "\n";
result = retry<5, 500>(func2, 1, 2);
std::cout << result << "\n";
result = retry<5, 500>(func2, 1, 0);
std::cout << result << "\n";
}
See example in coliru
This is simple enough with the execute-around idiom, which executes a given piece of code in an environment/set of circumstances controlled by the function the piece of code is passed in to. Here, we'll simply be calling the piece of code in a loop once every n milliseconds, either for a set amount of time, or for a set number of times.
Since you're working in an embedded environment and seem to be using a set of timing mechanisms different from that provided by <chrono> and <thread>, I've tried to adjust my answer so you can use the methods you seem to have access to to do the same thing. These are the functions I've used in my solution:
// similar functions to what you seem to have access to
namespace timing{
// interval defined as some arbitrary type
interval getInterval(int msCount);
bool intervalElapsed(interval i);
void await(interval i);
}
A note on the await function there--it takes an interval, and pauses execution until the interval has passed. It seems like the closest you can get to this might be simply waiting for the total number of milliseconds instead, though that strategy will introduce a certain amount of drift in your timings. If you can tolerate that (and given you're using it, it seems you can), then great.
The retry-for variant would look like this, given the above function signatures:
template <typename Func>
bool pollRetries(
int retryLimit,
int msInterval,
Func func){
for(int i = 0; i < retryLimit; ++i){
auto interval = timing::getInterval(msInterval);
if (func()){return true;}
timing::await(interval);
}
return false;
}
and the retry-while would look like this:
template <typename Func>
bool pollDuration(
int msLimit,
int msInterval,
Func func){
auto limit = timing::getInterval(msLimit);
while(!timing::intervalElapsed(limit)){
auto interval = timing::getInterval(msInterval);
if (func()){return true;}
timing::await(interval);
}
return false;
}
Live demo on Coliru
Both functions take a single functor which will be called with no arguments, and which returns either a boolean or something convertible to a boolean value. If the evaluation ever returns true, the loop will exit and the function will return true. Otherwise it'll return false at the end of the retry count or period.
Your sample code would convert to this:
retry for loop:
return pollRetries(5,1000,[simPinNumber](){
return unlockSIM(simPinNumber);
});
retry while loop:
return pollDuration(TIME_TO_WAIT_GPS, 500, [fixVal, this](){
int16_t
iRunStatus = 0,
iFixStatus = 0;
bool bRet = this->_pGsm->GPSstatus(&iRunStatus, &iFixStatus);
return bRet && (1 == iRunStatus) && (iFixStatus >= fixVal);
});
You can pass either functors or function pointers into these methods and the execution will occur, so you can also simply directly pass in lambdas to be executed. A few notes about that:
Lambdas without a capture group can be converted to function pointers with the unary + operator, allowing the template to use the function pointer instantiation of the template rather than one based off the lambda. You might want to do this because:
Every lambda in every function has an anonymous type. Passing the lambda into the template function will result in an additional template instantiation which might increase binary size.
You can also mitigate the above problem by defining your own functor class for uses that share a set of persistent state.
You might try making the timing functions into variadic templates per #stefaanv's solution. If you went this route, you could remove the capture groups from your lambdas and pass that information in manually, which would allow you to convert the lambdas into function pointers as though they were stateless.
Were most of these retry loops for a single class you could simply define the retry mechanisms as member function templates, and then subject yourself to member function pointers, thereby passing state around using the called object. I'd not recommend this though, as member function pointers are a bit of a pain to deal with, and you could get the same result by making a stateless lambda take a reference to the object, and passing in *this to the call. You'd also have to define all the bits of code as their own functions, rather than simply defining them within the function where they were used.
Is there any general way to refer to the current function being executed? Something that would let me do this for example,
([] (int n) -> int {
if (n <= 1) {
return 1;
}
return n * thisFunc(n - 1);
})()
Mainly, I'm thinking of anonymous functions calling themselves without the use of auxiliary named functions. So avoiding this.
You can use a function pointer, or function object in C++11, but there is no built-in way to refer to a function. For example:
std::function<int (int)> myFun = [] (int i)
{
if i <= 1
{
return 1;
}
return i * myFun(i-1);
}
I would argue that calling a lambda recursively is not how they were meant to be used. Lambdas are essentially meant to provide inline functionality and thus are meant to be fairly simple.
Not to mention that the example you give can very easily be replaced with a loop thus resulting in much more efficient implementation:
int result = 1;
while (i > 1)
{
result = result * i;
i--;
}