0

Started working for the first time really with headers and am running into a problem. I created a cpp file with a corresponding hpp file that i include in my main and also again in the cpp file now I get the following error:

[build] FAILED: test.exe 
[build] cmd.exe /C "cd . && C:\msys64\mingw64\bin\x86_64-w64-mingw32-g++.exe -g  CMakeFiles/test.dir/Main.cpp.obj CMakeFiles/test.dir/random.cpp.obj -o test.exe -Wl,--out-implib,libtest.dll.a -Wl,--major-image-version,0,--minor-image-version,0  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
[build] C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/test.dir/Main.cpp.obj:C:/Users/marks/Master_Project/mark-msc/Main.cpp:10: undefined reference to `cel::inputcells(std::vector<std::vector<cel::Bacteria, std::allocator<cel::Bacteria> >, std::allocator<std::vector<cel::Bacteria, std::allocator<cel::Bacteria> > > >&, int, int, int, int, int)'
[build] C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/test.dir/Main.cpp.obj: in function `main':
[build] C:/Users/marks/Master_Project/mark-msc/Main.cpp:25: undefined reference to `std::bitset<25> cel::random_bitset<25>(double)'
[build] C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/marks/Master_Project/mark-msc/Main.cpp:27: undefined reference to `cel::RotateParticles(std::vector<std::vector<cel::Bacteria, std::allocator<cel::Bacteria> >, std::allocator<std::vector<cel::Bacteria, std::allocator<cel::Bacteria> > > >&, int, int, std::bitset<25ull>)'
[build] collect2.exe: error: ld returned 1 exit status
[build] ninja: build stopped: subcommand failed.
[build] Build finished with exit code 1

Bascially it shows that there are undefined references to all the functions present in my CellLayer.cpp and hpp file. These look as followed:

CellLayer.cpp:

#include "random.hpp"
#include "CellLayer.hpp"


void cel::inputcells (std::vector<std::vector<Bacteria>> &CellGrid, int NrPfree, int NrP1, int NrP2, int NrP3, int N)
{
    for (int i = 0; i < NrPfree; ++i)
    {
        int randomnumber1 = rnd::uni_int(0, N); 
        int randomnumber2 = rnd::uni_int(0, N);

        CellGrid[randomnumber1][randomnumber2].alive = true;
    }
    for (int j = 0; j < NrP1; )
    {
        int randomnumber1 = rnd::uni_int(0, N); 
        int randomnumber2 = rnd::uni_int(0, N);

        if (!CellGrid[randomnumber1][randomnumber2].alive)
        {
            CellGrid[randomnumber1][randomnumber2].alive = true;
            std::bitset<3> P1 (std::string("001")) ;
            CellGrid[randomnumber1][randomnumber2].plasmid = P1;
            ++j;
        }
    }
    for (int p = 0; p < NrP2; )
    {
        int randomnumber1 = rnd::uni_int(0, N); 
        int randomnumber2 = rnd::uni_int(0, N);

        if (!CellGrid[randomnumber1][randomnumber2].alive)
        {
            CellGrid[randomnumber1][randomnumber2].alive = true;
            std::bitset<3> P2 (std::string("010")); 
            CellGrid[randomnumber1][randomnumber2].plasmid = P2;
            ++p;
        }
    }
    for (int l = 0; l < NrP3; )
    {
        int randomnumber1 = rnd::uni_int(0, N); 
        int randomnumber2 = rnd::uni_int(0, N);

        if (!CellGrid[randomnumber1][randomnumber2].alive)
        {
            CellGrid[randomnumber1][randomnumber2].alive = true;
            std::bitset<3> P3 (std::string("100")); 
            CellGrid[randomnumber1][randomnumber2].plasmid = P3;
            ++l;
        }
    }
}


std::bitset<25> cel::random_bitset(double p = 0.5) {

    std::bitset<25> bits;
    std::random_device rd;
    std::mt19937 gen(rd());
    std::bernoulli_distribution d(p);

    for( int n = 0; n < size; ++n) {
        bits[n] = d(gen);
    }

    return bits;
}

// Function to rotate and shift the margolus neighbourhood
void cel::RotateParticles(std::vector<std::vector<Bacteria>> &Cellgrid, int t, int N, std::bitset<25> bitseq)
{
    //offset for even and uneven timesteps 
    int offset = t % 2; 

    //for looping through bitseq
    int count = 0;

    for(int i0 = offset; i0 < N; i0 += 2) 
    {
        const int i1 = (i0 + 1) % N;
        for(int j0 = offset; j0 < N; j0 += 2) 
        {
            const int j1 = (j0 + 1) % N;;
            if(bitseq[count]) 
            {     
                // rotating clockwise
                Bacteria tmp = Cellgrid[i0][j0];
                Cellgrid[i0][j0] = Cellgrid[i0][j1];
                Cellgrid[i0][j1] = Cellgrid[i1][j1];
                Cellgrid[i1][j1] = Cellgrid[i1][j0];
                Cellgrid[i1][j0] = tmp; 
                ++count;
            } 
            else 
            {
                //rotating counterclockwise
                Bacteria tmp = Cellgrid[i0][j0];
                Cellgrid[i0][j0] = Cellgrid[i1][j0];
                Cellgrid[i1][j0] = Cellgrid[i1][j1];
                Cellgrid[i1][j1] = Cellgrid[i0][j1];
                Cellgrid[i0][j1] = tmp; 
                ++count;
            }
        }
    }
}
//not finished
void cel::Die (std::vector<std::vector<Bacteria>> &Cellgrid, std::vector<std::vector<std::vector<int>>> &system, std::vector<double> DchanceFree, std::vector<double> DchanceBear, std::pair<int, int>)
{
    std::vector<int> AntiB = {0, 1, 2};
    std::shuffle(std::begin(AntiB), std::end(AntiB), rnd::rn);
}

and the hpp file:

#ifndef CellLayer_hpp
#define CellLayer_hpp

#include <vector>
#include <iosfwd>
#include <string>
#include <memory> 
#include <bits/stdc++.h>

namespace cel
{ 
    class Bacteria {public: std::bitset<3> plasmid; bool alive; };
    void inputcells (std::vector<std::vector<Bacteria>> &CellGrid, int NrPfree, int NrP1, int NrP2, int NrP3, int N);
    std::bitset<25> random_bitset(double p = 0.5);
    void RotateParticles(std::vector<std::vector<Bacteria>> &Cellgrid, int t, int N, std::bitset<25> bitseq);
    void Die (std::vector<std::vector<Bacteria>> &Cellgrid, std::vector<std::vector<std::vector<int>>> &system, std::vector<double> DchanceFree, std::vector<double> DchanceBear, std::pair<int, int>);
}

#endif

Then in my main I have this:

#include "random.hpp"
#include "CellLayer.hpp"


int main()
{
    const int N = 10; 
    const int T = 5;
    std::vector<std::vector<cel::Bacteria>> gridab(N, std::vector<cel::Bacteria>(N));
    cel::inputcells(gridab, 1, 1, 1, 1, N);

    for (int j = 0; j < N; ++j)
    {  
        std::cout << "\n";
        for (int i = 0; i < N; ++i)
        {
            std::cout << gridab[j][i].alive << " ";
        }
    }
    std::cout << "\n";

    for (int t = 0; t < T; ++t)
    {
        std::bitset<25> bitseq;
        bitseq = cel::random_bitset( 0.5);

        cel::RotateParticles(gridab, t, N, bitseq);

        for (int j = 0; j < N; ++j)
        {  
            std::cout << "\n";
            for (int i = 0; i < N; ++i)
            {
                std::cout << gridab[j][i].alive << " ";
            }
        }
        std::cout << "\n";
    }


    return 0;
}

I truely have no idea why it's not working, as you can see I also have a random.hpp (& cpp) file which seem to be included just fine. If anyone has any insightes as to what may cause this problem that would be great.

M. Spa
  • 5
  • 3
  • fwiw, source files arent included. They are compiled and linked. How did you compile the code? – 463035818_is_not_an_ai Mar 30 '22 at 10:43
  • I believe they are; I build in the following way where i run all cpp files: # CMakeList.txt : CMake project for cmake-project cmake_minimum_required (VERSION 3.8) set(CMAKE_CXX_STANDARD 20) project(test) file(GLOB SOURCES "*.cpp") add_executable(test ${SOURCES}) – M. Spa Mar 30 '22 at 10:50
  • You're not linking with that file - the only inputs are "Main" and "random". – molbdnilo Mar 30 '22 at 10:50
  • What do you mean by inputs? I've included in both Main right so should it not be linked? – M. Spa Mar 30 '22 at 10:50
  • There is no "CellLayer" in your linking command line. Including headers has no effect on linking. `#include "foo"` literally only means "insert the contents of the file 'foo' here". – molbdnilo Mar 30 '22 at 10:52
  • please do not fix problems pointed out in answers in your question. The quesiton is for the broken code. Fixed code should go to answers – 463035818_is_not_an_ai Mar 30 '22 at 10:53
  • What exactly is my linking command line then? I'm sorry I really don't know what you mean by that – M. Spa Mar 30 '22 at 10:55
  • It's the second line of your output; "cmd.exe ...". (And do take some time to read about the compilation and linking process. There should be an overview in whatever you're learning from.) – molbdnilo Mar 30 '22 at 10:57
  • It was exactly that, apologies for not realizing sooner. It's working now :D – M. Spa Mar 30 '22 at 11:01
  • Please, provide Makefile source – shomeax Mar 30 '22 at 14:09

1 Answers1

1

The problem is that you've declared RotateParticles inside namespace cel while you're defining it inside global namespace instead of cel namespace.

To solve this you need to be in the scope of the namespace cel which you can do by qualifying it with cel:: as shown below:

CellLayer.cpp

//---vvv-------------------------------------------added cel:: here
void cel::RotateParticles(std::vector<std::vector<Bacteria>> &Cellgrid, int t, int N, std::bitset<25> bitseq)
{
     //other code as before
}

Similarly for other functions like inputcells, random_bitset etc.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • That is indeed something i forgot to adjust. But even after doing so the undefined refrence error remains. – M. Spa Mar 30 '22 at 10:39
  • @M.Spa Did you do this for all the three `RotateParticles`, `inputcells` and `random_bitset`? What exact error are you getting now? Note that you should implement the function template `random_bitset`inside the header file(.hpp) instead of source file. Refer to [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Jason Mar 30 '22 at 10:43
  • I did do it for all those functions. The error i get remains the same. Also i realized I did not need the template function so I removed the template part of it so most likely that is alsno not the problem. (I updated the code in the question) – M. Spa Mar 30 '22 at 10:48
  • @M.Spa These are linker errors. You need to add the appropriate source files(.cpp) like `CellLayer.cpp` in the list of source files when building your project. Also, please don't fix(edit) the original question by applying the things(fixes) said in any of the answer. This makes the answer pointless and obsolete. Instead apply the fixes in your own project. – Jason Mar 30 '22 at 10:58
  • Apologies for editing, What you said was in fact the problem thanks for the help – M. Spa Mar 30 '22 at 11:02