0

I'm trying to program a generic genetic algorithm in C++ using Visual Studio. To accomplish this, I'm making a couple of template classes. The template class I've made works fine when I put it in main.cpp, but I want to put it in a seperate header and cpp file. However I get many errors when I try to do it that way including "C2988 unrecognizable template declaration/definition". I'm hoping you can help with this.

Here's the header file:

//geno.h
#pragma once
//#include <iostream>
//#include "geno.cpp"

template <uint8_t NoChromo, uint32_t ChromoLength>
class geno
{
private:
    static const uint8_t NoMuTerms = 5;
    const float muTerms[3][NoMuTerms] = { { 1, 0, 0, 0, 0 },{ 0.02f, 0, 0, 0, 0 },{ -655.36f, 1, 1, 1, 1 }, };
    uint16_t mDNA[NoChromo][ChromoLength];
    uint8_t mExp[ChromoLength];
public:
    //constructor
    geno();
    //destructor
    ~geno();
    //copy constructor
    geno(const geno& og);
    //assignment operator
    void operator=(const geno& og);
private:
    //functions
    void print();
public:
    void genRand();
private:
    geno crossover() const;
    static geno recombine(const geno parents[NoChromo]);
    geno mutate() const;
public:
    static geno reproduce(const geno parents[NoChromo]);
};

#include "geno.cpp"

Here's geno.cpp

//#include "geno.h"
#include <iostream>
#include <random>
#include <ctime>

using namespace std;

mt19937 rng(std::time(0));
uniform_int_distribution<uint16_t> distr(0, 65535);

//Constructor
template <uint8_t NoChromo, uint32_t ChromoLength> 
geno<NoChromo, ChromoLength>::geno()
{}

//Destructor
template <uint8_t NoChromo, uint32_t ChromoLength> 
geno<NoChromo, ChromoLength>::~geno()
{}

//Copy constructor
template <uint8_t NoChromo, uint32_t ChromoLength> 
geno<NoChromo, ChromoLength>::geno(const geno<NoChromo, ChromoLength>& og)
{
    for (uint32_t j = 0; j < ChromoLength; ++j)
    {
        mExp[j] = og.mExp[j];
        for (uint8_t i = 0; i < NoChromo; ++i)
        {
            mDNA[i][j] = og.mDNA[i][j];
        }
    }
}

//Assignment operator
template <uint8_t NoChromo, uint32_t ChromoLength> 
void geno<NoChromo, ChromoLength>::operator=(const geno<NoChromo, ChromoLength>& og)
{
    for (uint32_t j = 0; j < ChromoLength; ++j)
    {
        mExp[j] = og.mExp[j];
        for (uint8_t i = 0; i < NoChromo; ++i)
        {
            mDNA[i][j] = og.mDNA[i][j];
        }
    }
}

//print
template <uint8_t NoChromo, uint32_t ChromoLength> 
void geno<NoChromo, ChromoLength>::print()
{
    for (uint32_t i = 0; i < ChromoLength; ++i)
    {
        for (uint8_t j = 0; j < NoChromo; ++j)
        {
            cout << mDNA[j][i] << " ";
        }
        cout << int(mExp[i]);
        cout << endl;
    }
    cout << endl;
}

//genRand
template <uint8_t NoChromo, uint32_t ChromoLength> 
void geno<NoChromo, ChromoLength>::genRand()
{
    for (uint32_t j = 0; j < ChromoLength; ++j)
    {
        for (uint8_t i = 0; i < NoChromo; ++i)
        {
            mDNA[i][j] = distr(rng);
        }
        mExp[j] = distr(rng) % NoChromo;
    }
    ///*
    cout << "random:" << endl;
    print();
    //*/
}

//crossover
template <uint8_t NoChromo, uint32_t ChromoLength> 
geno<NoChromo, ChromoLength> geno<NoChromo, ChromoLength>::crossover() const
{
    geno PH;
    uint8_t die;
    for (uint32_t i = 0; i < ChromoLength; ++i)
    {
        die = distr(rng);
        for (uint8_t j = 0; j < NoChromo; ++j)
        {
            PH.mDNA[j][i] = mDNA[(j + die) % NoChromo][i];
        }
    }
    ///*
    cout << "crossover:" << endl;
    PH.print();
    //*/
    return PH;
}

//recombine
template <uint8_t NoChromo, uint32_t ChromoLength> 
geno<NoChromo, ChromoLength> geno<NoChromo, ChromoLength>::recombine(const geno<NoChromo, ChromoLength> parents[NoChromo])
{
    geno PH;
    uint8_t die;
    for (uint8_t i = 0; i < NoChromo; ++i)
    {
        die = distr(rng) % NoChromo;
        for (uint32_t j = 0; j < ChromoLength; ++j)
        {
            PH.mDNA[i][j] = parents[i].mDNA[die][j];
        }
    }
    ///*
    cout << "recombine:" << endl;
    PH.print();
    //*/
    return PH;
}

//mutate
template <uint8_t NoChromo, uint32_t ChromoLength> 
geno<NoChromo, ChromoLength> geno<NoChromo, ChromoLength>::mutate() const
{
    geno PH;
    uint16_t die;
    for (uint8_t i = 0; i < NoChromo; ++i)
    {
        for (uint32_t j = 0; j < ChromoLength; ++j)
        {
            die = distr(rng);
            PH.mDNA[i][j] = 1;
            for (uint8_t k = 0; k < NoMuTerms; ++k)
            {
                PH.mDNA[i][j] = PH.mDNA[i][j] * (muTerms[0][k] * mDNA[i][j] + muTerms[1][k] * die + muTerms[2][k]);
            }
        }
    }
    ///*
    cout << "mutate:" << endl;
    PH.print();
    //*/
    return PH;
}

//reproduce
template <uint8_t NoChromo, uint32_t ChromoLength> 
geno<NoChromo, ChromoLength> geno<NoChromo, ChromoLength>::reproduce(const geno<NoChromo, ChromoLength> parents[NoChromo])
{
    geno PH1[NoChromo];
    geno PH2;
    for (uint8_t i = 0; i < NoChromo; ++i)
    {
        PH1[i] = parents[i].crossover();
    }

    PH2 = recombine(PH1);
    PH2 = PH2.mutate();
    return PH2;
}

And here are the errors I'm getting:

Severity    Code    Description Project File    Line    Suppression State
Error   C2182   'geno': illegal use of type 'void'  evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 51  
Warning C4244   'argument': conversion from 'time_t' to 'unsigned int', possible loss of data   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 8   
Error   C2988   unrecognizable template declaration/definition  evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 13  
Error   C2143   syntax error: missing ';' before '<'    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 13  
Error   C2059   syntax error: '<'   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 13  
Error   C2588   '::~geno': illegal global destructor    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 18  
Error   C2143   syntax error: missing ';' before '{'    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 19  
Error   C2447   '{': missing function header (old-style formal list?)   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 19  
Error   C2988   unrecognizable template declaration/definition  evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 23  
Error   C2143   syntax error: missing ';' before '<'    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 23  
Error   C2059   syntax error: '<'   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 23  
Error   C2143   syntax error: missing ';' before '{'    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 38  
Error   C2447   '{': missing function header (old-style formal list?)   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 38  
Error   C2988   unrecognizable template declaration/definition  evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 51  
Error   C2143   syntax error: missing ';' before '<'    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 51  
Error   C2059   syntax error: '<'   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 51  
Error   C2143   syntax error: missing ';' before '{'    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 68  
Error   C2447   '{': missing function header (old-style formal list?)   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 68  
Error   C2988   unrecognizable template declaration/definition  evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 85  
Error   C2143   syntax error: missing ';' before '<'    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 85  
Error   C2059   syntax error: '<'   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 85  
Error   C2143   syntax error: missing ';' before '{'    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 107 
Error   C2447   '{': missing function header (old-style formal list?)   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 107 
Error   C2988   unrecognizable template declaration/definition  evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 127 
Error   C2143   syntax error: missing ';' before '<'    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 127 
Error   C2059   syntax error: '<'   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 127 
Error   C2143   syntax error: missing ';' before '{'    evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 153 
Error   C2447   '{': missing function header (old-style formal list?)   evolution1  c:\users\dehim\documents\windesheim\2de jaar!\software\projecten\evolution1\evolution1\geno.cpp 153 

Here's my main.cpp:

#include <iostream>
#include <random>
#include <ctime>
#include "geno.h"

using namespace std;

int main()
{
    const uint8_t NoChromo = 3;
    const uint32_t ChromoLength = 10;


    geno<NoChromo, ChromoLength> a[NoChromo];
    for (uint8_t i = 0; i < NoChromo; ++i)
    {
        a[i].genRand();
    }
    geno<NoChromo, ChromoLength> b = geno<NoChromo, ChromoLength>::reproduce(a);
    cin.get();
}

I've already tried a lot of things and searched the web, but can't figure out what I'm doing wrong.

Thanks in advance,

Dehim

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Dehim
  • 61
  • 3
  • 1
    I see you put your definitions in a `.cpp` file. Is that file perhaps being compiled separately? It doesn't seem to include `geno.h`. – François Andrieux Jul 27 '18 at 14:20
  • @NathanOliver `geno.h` has `#include "geno.cpp"` at the bottom which likely caused problems. And then removing `#include "geno.h"` from the `.cpp` would get ride of them. – François Andrieux Jul 27 '18 at 14:21
  • @FrançoisAndrieux So it does. I missed that. – NathanOliver Jul 27 '18 at 14:22
  • @NathanOliver, Yes, both ways give a bunch of errors, I just thought this way was the lesser of the two evils. – Dehim Jul 27 '18 at 14:33
  • If you rename `geno.cpp` to `geno.tpp` and then turn `#include "geno.cpp"` at the end of `geno.h` into `#include "geno.tpp"` does it then work? – NathanOliver Jul 27 '18 at 14:36
  • @NathanOlive, Nope, same errors. – Dehim Jul 27 '18 at 14:42
  • [I cannot reproduce when making that change](https://wandbox.org/permlink/GUQlgRgWWLtHyD9a) – NathanOliver Jul 27 '18 at 14:46
  • @NathanOliver, That's weird, it also works with my main in that browser app, but it still doesn't work for me in visual studio. Have you tried it in visual studio? I've also added my main to my original question. – Dehim Jul 27 '18 at 15:06
  • Make sure `geno.cpp`/`geno.tpp` is in the header file folder and not the source file folder in the solution explorer. – NathanOliver Jul 27 '18 at 15:09
  • same errors still. – Dehim Jul 27 '18 at 15:13
  • Template classes should usually be fully defined in the header (can be outside of declaration). You should only define template classes in source (.cpp) files if you explicitly declare what is allowed to instantiate the template, seen [here](https://stackoverflow.com/questions/115703/storing-c-template-function-definitions-in-a-cpp-file). What command are you using to compile? Once you turn `geno.cpp` into `geno.hpp` you should not try to compile it but just the `main.cpp` – LemonPi Jul 27 '18 at 15:56
  • @LemonPi, I'm just clicking Local Windows Debugger and have it set to Debug, x86. I've turned geno.cpp into geno.hpp. How do I only compile main.cpp and then run it? – Dehim Jul 27 '18 at 16:08
  • I've deleted the .hpp file and added it again as an hpp file under headers in the solution explorer and now it works! – Dehim Jul 27 '18 at 21:07

1 Answers1

0

I've deleted the implementation file and added it again as a .hpp file under headers in the solution explorer. I also changed #include "geno.cpp" at the bottom of my .h file into #include "geno.hpp" and now it works! (I had to add geno.hpp as a .hpp file and not as a .cpp file that I changed into .hpp file.) Thanks to everyone who commented on this question for their time, effort and ideas.

Nevermind, doing it the way described above, doesn't allow me to change the implementation once it's compiled. I have to delete the .hpp file, add it again, change the implementation and then compile it, just to recompile. A friend of mine recommended me CLion, so tomorrow I'll check if CLion does it any better.

EDIT: Now I can change the implementation for some reason...

Dehim
  • 61
  • 3