1

I'm having trouble in a part of my program where I pass an object that acts as a lambda function to another function (I need to capture a const this pointer so I can't use an actual lambda). This causes the copy constructor of my lambda to be called, which again calls the copy constructor, and eventually the stack overflows. I understand what's happening but I'm not sure why the copy constructor is calling itself or how to fix this. I've reproduced the problem below.

Compiler: MSVC 2010

#include <functional>

void synchronizedExecution(std::function<void()> function) {
    function();
}

int main(int argc, char *argv[])
{

    int b = 0;

    class Function : public std::function<void()> {
    public:
        int& b;
        Function(int& b) :
            b(b) {}
        void operator()() {}
    } function(b);

    synchronizedExecution(function);

    return 0;
}
HahaHortness
  • 1,570
  • 1
  • 15
  • 16

2 Answers2

3

I can help you with the "how to fix this" part - change your function to

void synchronizedExecution(const std::function<void()>& function)
PaF
  • 3,297
  • 1
  • 14
  • 15
  • Depends, I can see where the user would like the function to actually be copied (since synchronizedExecution is a function, I'm guessing async is also an option) – IdeaHat Feb 06 '14 at 20:00
  • @MadScienceDreams: Passing by value would be [slicing](http://stackoverflow.com/q/274626/10077). Bad news. – Fred Larson Feb 06 '14 at 20:03
  • @FredLarson I was thinking that but it doesn't expload in g++ and I'm still trying to figure out why... – IdeaHat Feb 06 '14 at 20:05
  • @MadScienceDreams: I bet it doesn't call `Function::operator()()`, either. – Fred Larson Feb 06 '14 at 20:07
  • My code was growing in a way that made me think that even if I passed by reference I would have to copy the function at some point. But now I don't think that's the case, so I think this will work. – HahaHortness Feb 06 '14 at 20:07
  • @FredLarson I think (i could be wrong) that his code is actually interpreted as the implicite functor-type constructor for std::function rather than as a literal type, so it creates a copy of the Function class as a member rather than it being sliced. I have no proof of this. – IdeaHat Feb 06 '14 at 20:12
  • @MadScienceDreams: Actually, I don't think it will work either way, as `std::function::operator()()` is not virtual. It's not meant to be used as a base class. – Fred Larson Feb 06 '14 at 20:14
  • @FredLarson added manual copy constructor, `std::function fun = function` definitely calls Function::Function(const Function& fun), synchornizedExecution(function) calls the copy constructor twice (once for creating the implicitly casted std::function, once for the copy into the function). So no slicing, atleast with real C++11. – IdeaHat Feb 06 '14 at 20:18
  • @MadScienceDreams: I get it now, and you're right. There's no slicing here. – Fred Larson Feb 06 '14 at 20:45
0

First, to solve your problem you can probably pass object by reference, not by value.

Second, your coding is very prone to errors. When you introduce a new name and it is the same as the existing one, you have a collision which compiler solves but you not always get what you expected. For example

   class Function
        int& b;
        Function(int& b) :
            b(b) {}

I am honestly not sure, which b will be substituted into (), the class member or the function parameter. AFAIR, the class member has precedence and this is not what you intended. I suspect your actual problem has the same cause.

Michael Simbirsky
  • 3,045
  • 1
  • 12
  • 24