1

Recently, I have been working in JS canvas to make fractals in two and three dimensions. Right now, I am working on porting my project into C++ via SDL and Eigen. It's pretty important that I am able to compose functions for later use. The code below is my first attempt at making a composite function factory:

std::function< Eigen::Vector3f(Eigen::Vector3f) > compose3d(std::function< 
Eigen::Vector3f(Eigen::Vector3f) > a, std::function< 
Eigen::Vector3f(Eigen::Vector3f) > b){
    return [&](Eigen::Vector3f vec)->Eigen::Vector3f{
        return b(a(vec));
    };
}

Currently this is giving me a duplicate symbol error during linking. If this code is removed, the error goes away. I have made sure that this function is inside of a ifndef section of my header. I know it is not best practice to have functions fully defined in the header, but would like to get things working before refactoring.

Overall, I just want to know if this problem is an error in the writing of the function if I should look somewhere else in my code for duplicate definitions. I am aware that it is considered better to create lists of function pointers rather than to create lists of functions and I will work on implementing that after this linker error is solved.

Sorry if this is horrendous, I haven't been writing C++ very long and this is my first lambda attempt.

Thanks!

2 Answers2

0

Declare it "inline". Otherwise every file that includes the header file will create a separate function with that signature.

Jive Dadson
  • 16,680
  • 9
  • 52
  • 65
0

The linking problem is most likely because you have the function definition in a header file which is included in mulitple compilation units. This results in duplicate definition errors. You need to either move the declaration to a single compilation (leaving just a declaration in the header file), or make the function static or inline, which allows mulitple definitions in different compilation units.

A much bigger problem is the fact that you bind by reference to the function arguments and then return the lambda with the bound references. These references will become dangling after the function returns, leading to undefined behavior when you try to call the returned lambda. It's a particularly noxious error, as its likely to work for simple examples and tests programs (with everything inlined) and fail for more complex cases.

To fix that, you need to bind the arguments by value instead of by reference -- use [=] instead of [&].

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226