Consider a normal recursive function:
#include <iostream>
#include <functional>
void f(unsigned long long int x) {
std::cout << x << "\n";
if(x < 1e9)
f(x+1);
}
int main() {
f(1);
return 0;
}
This terminates at 43033.
Now consider a recursive lambda:
#include <iostream>
#include <functional>
int main() {
std::function<void(int)> g = [&g](unsigned long long int x) {
std::cout << x << "\n";
if(x < 1e9)
g(x+1);
};
g(1);
return 0;
}
This terminates at a much lower stack depth of 11736.
Why do lambdas have a lower max stack depth?
(Compiling with g++ (GCC) 5.4.0, with -std=c++14 -Wall)
Also note that compiling with -O3 optimization allows for practically infinite recursion depth, but the lambda still terminates at 25k.
EDIT: Following #Yakk, here are results with the Y-combinator:
#include <iostream>
#include <functional>
using namespace std;
template <typename T, typename R>
function<R(T)> Y(function<function<R(T)>(function<R(T)>)> f) {
// Y f = f (λx.(Y f) x)
return f([=](T x) { return Y(f)(x); });
}
int main() {
using fg = function<void(int)>;
function<fg(fg)> sg = [](fg g) {
return [g](unsigned long long int x) {
std::cout << x << "\n";
if(x < 1e9)
g(x+1);
};
};
Y(sg)(1);
return 0;
}
This terminates at 4781 and 9221 with and without -O3 respectively.
std function does not mean the same thing as lambda. A std function is an object capable of storing some lambdas, or a function pointer, or a pointer to member function, or a pointer to member data, or almost any object that overrides operator() compatibly.
When you store a lambda within a std function, there is some overhead. Not much, but some. Some of this overhead may show up as using the stack more (and the overhead will be larger in unoptimized builds).
You can more directly recurse using a lambda by using the y combinator, but even there you'll be passing a reference-to-self as a parameter, and unless the recursion is eliminated by the optimizer it will probably use more stack. (A highly tweaked optimizer could notice that a stateless lambda reference argument could be eliminated, but that seems tricky to work out).
Related
In the following code:
#include <iostream>
#include <type_traits>
// this code below won't compile unless at this point there is already
// a typename rate
// using rate = std::integral_constant<int, 10>;
template<typename rate=rate> void functionA()
{
static_assert(rate::value > 5);
std::cout << "functionA: " << rate::value << std::endl;
}
template<typename rate> void loop()
{
functionA<std::integral_constant<int, 50>>(); // => prints "functionA: 50"
functionA(); // <- I would like this call to infer loop's functions's rate template type (which would be 20)
}
void other()
{
using rate = std::integral_constant<int, 12>;
functionA(); // => prints "functionA: 12"
}
void bare_loop()
{
functionA(); // should give compile time-error: no 'rate' in semantic scope
}
int main() {
loop<std::integral_constant<int, 20>>();
return 0;
}
I would like to be able to write a templated function which has a default parameter value which remains undeclared until compilation is necessary.
The above shows the most minimal piece of code to express this idea.
What I'm trying to achieve is directly inspired by Lisp's variable capture mechanism (lexical and dynamic scope).
To be clear: this is entirely a compile-time problem and solution.
Is this possible in the current state of affaires of C++?
I am really not sure if I understood what you intended, but if you want is a function that could either take the parameter rate at compile time or at runtime, well, one possibility would be to use a default parameter in function "functionA", determined by the template parameter. So you can define the default in compile time, and override it in runtime if needed.
I leave an example below in case it helps, however I can't understand what it the desired use case, and it can be possibly
a bad design:
#include <iostream>
#include <cassert>
constexpr int infer() { return 123; }
const int MIN_RATE_LIM = 5;
template<int t_rate=infer()> void functionA(const int rate = t_rate)
{
assert(rate > MIN_RATE_LIM);
std::cout << "functionA: " << rate << std::endl;
}
template<int rate> void loop()
{
for(int i = 0; i < 10; i++ )
{
functionA<50>();
functionA<rate>();
functionA<rate>(12); // <- 12 will overlap the value 10 in this line
}
}
int main() {
loop<10>();
return 0;
}
I try to create a simple program in which I want to create vector of future arguments.
I created a wrapper function which is used to submit lambda functions and stores internally in a vector the future objects
I use an intermediate step in which I create an initiliazer_list using variadic arguments . But fails to compile. I try to use to call a function in order to push the elements in the vector and fails to compile as well
Below is the code
#include <iostream>
#include <thread>
#include <future>
#include <functional>
#include <cstdlib>
#include <chrono>
#include <initializer_list>
using namespace std;
using FunctPtr = function<int(int, int) >;
using FutureInt = future<int>;
using AsyncVector = vector<FutureInt>;
AsyncVector asyncVec;
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
auto initList {pFunc... };
for (auto & element : initList)
{
asyncVec.emplace_back(async(launch::async, element,4,5));
}
}
int main()
{
int a;
int b;
auto addPtr = [](int x, int y)->int
{
std::cout << "add :" << x + y << std::endl;
return x + y;
};
auto multPtr = [](int x, int y)->int
{
std::cout << "mult :" << x * y << std::endl;
return x * y;
};
// submit(add,4,5);
submit(addPtr, multPtr);
for (auto & v : asyncVec)
{
std::cout << "Wait for " << v.get() << std::endl;
}
}
Yes, they are of different types so cannot be in the same init-list easily.
Your best options should probably be:
Either push them all into asyncVec in the same fold-expression.
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
(asyncVec.emplace_back(async(launch::async, std::move(pFunc), 4, 5)), ...);
}
Or, if they all are of the same signature, type-erase them, like keeping them in an array of std::function.
template<typename... TemplatePtr>
void submit(TemplatePtr... pFunc)
{
for (auto &&element: {std::function<int(int, int)>(std::move(pFunc))...})
{
asyncVec.emplace_back(async(launch::async, std::move(element), 4, 5));
}
}
(I have specified function signature explicitly though compiler should be able to deduce it.)
Or, if all closures are captureless and of the same signature, simply cast them to the same type when calling submit:
using SameType = int (*)(int, int);
submit(static_cast<SameType>(addPtr), static_cast<SameType>(mulPtr));
This way your original submit should work as is.
Context: On one of my C++11 application, object serialization and publish of message is time consuming. Therefore I want to do it in a separate thread using Intel TBB library (more specifically using a tbb::task_group)
Issue: the object to serialize is a struct where some of the properties are std::vector<std::unique_ptr<SomeObject>>, making it impossible to pass by copy to the lambda executed in a task
Approximately it look like
struct MockedDC {
MockedDC(int x, std::vector<std::unique_ptr<SomeObject>> v) : x(x),
v(std::move(v)) {};
int x;
std::vector<std::unique_ptr<SomeObject>> v;
};
The "solution" I found, is to reconstruct on the heap with the move-constructor my instance and wrap it in a shared_ptr<MockedDC> which is copyable. In the end the function which invoke the tbb::task_group::run look like
// function called like this `executeInThread(taskGroup, std::move(mockedDC))`
void executeInThread(tbb::task_group& taskGroup, MockedDC mockedDC) {
const std::shared_ptr<MockedDC> sharedMockedDC(new MockedDC(std::move(mockedDC)));
auto f = [sharedMockedDC] {
const auto serialized(serializer(*sharedMockedDC)); // pass by reference
publish(serialized);
};
taskGroup.run(f);
};
it compile and run fine, but I can't put it under pressure as it will be in real life condition
so my question is is it safe/sane to do this ?
I found on another stackoverflow question an alternative, but the implementation looks difficult to maintain given my C++ knowledge :) that's why I want to stick with the shared_ptr approach as suggested somewhere else
What I tried so far: I wrote a dummy code to test the thing, but I think its not enough to validate this approach. I also wanted to compile with some sanitization flags, but tbb fail to link with a bunch of errors like undefined reference to __ubsan_handle_pointer_overflow
Here is the dummy example if that help to answer (it compile and run without issues (except some int overflow but that not an issue I guess))
#include <cstdio>
#include <iostream>
#include <memory>
#include <vector>
#include <numeric>
#include "tbb/task_scheduler_init.h"
#include "tbb/task_group.h"
struct MockedDC {
MockedDC(int seed, size_t baseLen) : seed(seed), baseLen(baseLen) {
this->a_MDC.reserve(baseLen);
for (size_t i = 0; i < baseLen; ++i)
this->a_MDC.emplace_back(new int((seed + i) / (seed + 1)));
};
int seed;
size_t baseLen;
std::vector<std::unique_ptr<int>> a_MDC;
};
void executeInThread(tbb::task_group& taskGroup, MockedDC mockedDC) {
const std::shared_ptr<MockedDC> sharedMockedDC(new MockedDC(std::move(mockedDC)));
auto f = [sharedMockedDC] {
std::cout <<
std::accumulate(sharedMockedDC->a_MDC.begin(), sharedMockedDC->a_MDC.end(), 0, [](int acc, const std::unique_ptr<int>& rhs) {
return acc + *rhs;
})
<< std::endl << std::flush;
};
taskGroup.run(f);
};
void triggerTest(tbb::task_group& taskGroup) {
for (size_t i = 0; i < 1000000; ++i) {
MockedDC mdc(i, 10000000);
executeInThread(taskGroup, std::move(mdc));
}
return ;
};
int main() {
tbb::task_scheduler_init tbbInit(tbb::task_scheduler_init::automatic);
//tbb::task_scheduler_init tbbInit(8);
tbb::task_group taskGroup;
triggerTest(taskGroup);
taskGroup.wait();
return (0);
};
PS: using C++14 new capture by move doesn't work because of TBB library :/
I have a code where I have two options, define lambda out of loop to save on lambda creation overhead or define it inside a loop to keep small scope.
Is this choice critical and will make any significant difference?
What are pros and cons of this two choices?
What is best practice?
#include <iostream>
#include <string>
#include <vector>
#include <memory>
int main()
{
std::vector<std::function<void()>> functors;
auto func = [] () { std::cout << "Hello world I am doing some action"; };
//some code here
for(int i = 0; i < 100; ++i)
{
// some code here
functors.push_back(func);
// some code here
}
}
EDITED: simplified example
int main()
{
auto sum = [](const int x, const int y) { return x + y; };
for(int i = 0; i < 100; ++i)
{
std::cout << sum(i, i + 1) << std::endl;
}
}
For each lambda expression, the compiler will create a struct with operator () overloaded for it. It won't create a struct each time the control passes through a lambda, so in terms of generated code it does not matter whether you define it inside or outside the loop. Therefore, keep things local.
As a general rule, don't overthink these illusory optimization issues. Most likely, the performance bottleneck is going to be in your algorithm complexity.
I'd rather wipe out a copy construction and move construct instead by using emplace_back directly (not so useful in this case, but as a rule of thumb one should prefer it whenever possible):
#include <iostream>
#include <string>
#include <vector>
#include <memory>
int main()
{
std::vector<std::function<void()>> functors;
//some code here
for(int i = 0; i < 100; ++i)
{
// some code here
functors.emplace_back([] () { std::cout << "Hello world I am doing some action"; });
// some code here
}
}
That said, I agree with #ArmenTsirunyan and I'd avoid premature optimizations of such a type.
I want to save the "binder" of a function to a variable, to use it repetitively in the following code by exploiting its operator overloading facilities. Here is the code that actually does what I want:
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
class X
{
int n;
public:
X(int i):n(i){}
int GetN(){return n;}
};
int main()
{
using namespace std;
using namespace boost;
X arr[] = {X(13),X(-13),X(42),X(13),X(-42)};
vector<X> vec(arr,arr+sizeof(arr)/sizeof(X));
_bi::bind_t<int, _mfi::mf0<int, X>, _bi::list1<arg<1> > > bindGetN = bind(&X::GetN,_1);
cout << "With n =13 : "
<< count_if(vec.begin(),vec.end(),bindGetN == 13)
<< "\nWith |n|=13 : "
<< count_if(vec.begin(),vec.end(),bindGetN == 13 || bindGetN == -13)
<< "\nWith |n|=42 : "
<< count_if(vec.begin(),vec.end(),bindGetN == 42 || bindGetN == -42)
<< "\n";
return 0;
}
What bothers me is, of course, the line:
bi::bind_t<int, _mfi::mf0<int, X>, _bi::list1<arg<1> > > bindGetN = bind(&X::GetN,_1);
I've obtained the type just by deliberately making a type error and analysing the error message. That is certainly not a good way to go. Is there a way to obtain the type for the "bindGetN"? Or, maybe there are different ways to produce similar functionality?
Edit: I forgot to mention that the, so to say, "standard" suggestion to use function is not working in this case -- because I'd like to have my operator overloading.
The short answer is: you don't need to know (implementation defined).
It is a bind expression (std::tr1::is_bind_expression<T>::value yields true for the actual type).
Look at
std::tr1::function<>
BOOST_AUTO()
c++0x 'auto' keywords (Type Inference)
it's close cousing decltype() can help you move further
1.
std::tr1::function<int> f; // can be assigned from a function pointer, a bind_expression, a function object etc
int realfunc();
int realfunc2(int a);
f = &realfunc;
int dummy;
f = tr1::bind(&realfunc2, dummy);
2.
BOOST_AUTO() aims to support the semantics of c++0x auto without compiler c++0x support:
BOOST_AUTO(f,boost::bind(&T::some_complicated_method, _3, _2, "woah", _2));
3.
Essentially the same but with compiler support:
template <class T> struct DoWork { /* ... */ };
auto f = boost::bind(&T::some_complicated_method, _3, _2, "woah", _2));
DoWork<decltype(T)> work_on_it(f); // of course, using a factory would be _fine_
Note that auto has probably been invented for this kind of situation: the actual type is a 'you don't want to know' and may vary across compilers/platforms/libraries