undefined reference, stupid

Hello,

I'm frustrated finding the error. I don't know if I am just stupid or if my IDE/compiler is trolling me.

The case is, three files and the following error:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef WORLD_HPP
#define	WORLD_HPP

#include <iostream>
#include <vector>

template<int ROWS, int COLS>
class World{
private:
    enum caselles{X, O};
    
    std::vector<short unsigned int> aux;
public:
    World();
    World(const World&);
};

#endif	/* WORLD_HPP */ 


1
2
3
4
5
6
7
8
9
10
11
#include "World.hpp"

template<int ROWS, int COLS>
World<ROWS,COLS>::World() : aux(ROWS*COLS){
        std::cout << "Created a World empty " << std::endl;
}

template<int ROWS, int COLS>
World<ROWS,COLS>::World(const World<ROWS,COLS>& in){
    std::cout << "Created a World by copy " << std::endl;
}


1
2
3
4
5
6
7
8
9
10
11
12
#include <cstdlib>
#include "World.hpp"

using namespace std;

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

    World<2,2> a;
    World<2,2> b(a);
    
    return 0;
}


main.cpp:15: undefined reference to `World<2, 2>::World()'
main.cpp:16: undefined reference to `World<2, 2>::World(World<2, 2> const&)'

Opinions?
The compiler should see template definitions then it compiles code. So place all your template definitions of World in one header file and use it where template World is used.
Templates must be defined in the same translation unit where they are being used. Put the definition of the World constructors in World.hpp and it should work better.
Could any of your to put an example.

And, another question. How could solve this problem using the word extern?

Thank you!
closed account (S6k9GNh0)
1. You can't solve this with the word extern.
2. You can solve this by putting "class template World<2, 2>;"
3. You should realize how restricting this is to be placed in the implementation itself and not inlined.

Also, extern cannot solve the problem because type data isn't portrayed in binary (aside from debugging info but that's different entirely).

Instead, you should place the implementation of the template class in a header which ascertains it to being inlined (in 99% of cases anyways).
closed account (zb0S216C)
Another solution is using in-line files. In-line files contain the definition of templates. The file is then #included at the bottom of the header where the declaration is. The extension can be anything other than the extensions for header/source modules. For example:

Header:
1
2
3
4
5
6
7
8
#ifndef __HEADER_DEF__
#define __HEADER_DEF__

template< typename Type >
void Function( const Type &In_Data );

#include "In-line File.inl"
#endif 


In-line File:
1
2
3
4
5
template< typename Type >
void Function( const Type &In_Data )
{
    //...
}

...which is equivalent to:
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef __HEADER_DEF__
#define __HEADER_DEF__

template< typename Type >
void Function( const Type &In_Data );

template< typename Type >
void Function( const Type &In_Data )
{
    //...
}

#endif 


Wazzak
Last edited on
closed account (S6k9GNh0)
What benefits, if any, does that give?
closed account (zb0S216C)
It helps by separating the definition from the declaration. It's especially useful for large template declarations, such as classes. I find it useful.

Wazzak
I think this is done to hide realization.
Last edited on
closed account (S6k9GNh0)
You're still required to include everything inside of the "inl" file which increases compile-times, you're required to repeat literally every single template definition a second time, it adds yet another file into the codebase, and reduces code-readability since you must open yet another file to figure out the definition of the template functions.

Yeah, sorry, won't be using that one anytime soon.
closed account (zb0S216C)
¬_¬

Wazzak
@Framework

And if I don't want to get my function in-lined? How should I use your idea?
I read about it but really don't get it.


@computerquip

I don't know how use yours, be more specific please about class template Would<2,2>;
An example pls

THX you guys
closed account (S6k9GNh0)
Aikon, you have two options:

1) Inline your template function.
2) Explicitly declare your template function/class with template parameters to make an instance of that template in implementation. Generally called "explicit template instantiation".

The first one is simple and flexible. The second one is confusing, inflexible, and really bad practice (in most cases). In your case, you *want* to inline your template because there's generally never going to be a case where you know what template parameters you pass to the template function.
Last edited on
Got it! Thank you!
Topic archived. No new replies allowed.