More templates

H

Hans

Hi All,

In the stripped down code example below Visual C++ 2005 issues the following
error:

error LNK2019: unresolved external symbol "public: void __thiscall
Addsub<24>::do_process123(void)"

This is a SystemC example, however I believe this is a basic C++ syntax
error since if I move the Addsub function inside the Addsub class (that is
delete File2) then all is OK so I must have made a mistake in the template
definition?

Thanks,
Hans.

// File 1 addsub.h
template <int ADDSUB_WIDTH=24>
SC_MODULE(Addsub)
{

void do_process123(); // fails
void do_process123() {}; // works, excl addsub.cpp

SC_CTOR(Addsub) {
SC_METHOD(do_process123);
}
};

// File 2 addsub.cpp
template <int ADDSUB_WIDTH>
void Addsub<ADDSUB_WIDTH>::do_process123(){}

// File 3 top.h
#include "addsub.h"

#define WIDTH 24

SC_MODULE(Cordic) {
public:

Addsub<WIDTH> ADD1;

void do_process1() { }
SC_CTOR(Cordic) : ADD1("ADD1") {
SC_METHOD(do_process1);
}
};
 
M

mlimber

Hans said:
Hi All,

In the stripped down code example below Visual C++ 2005 issues the following
error:

error LNK2019: unresolved external symbol "public: void __thiscall
Addsub<24>::do_process123(void)"

This is a SystemC example, however I believe this is a basic C++ syntax
error since if I move the Addsub function inside the Addsub class (that is
delete File2) then all is OK so I must have made a mistake in the template
definition?

Thanks,
Hans.

// File 1 addsub.h
template <int ADDSUB_WIDTH=24>
SC_MODULE(Addsub)
{

void do_process123(); // fails
void do_process123() {}; // works, excl addsub.cpp

SC_CTOR(Addsub) {
SC_METHOD(do_process123);
}
};

// File 2 addsub.cpp
template <int ADDSUB_WIDTH>
void Addsub<ADDSUB_WIDTH>::do_process123(){}

// File 3 top.h
#include "addsub.h"

#define WIDTH 24

SC_MODULE(Cordic) {
public:

Addsub<WIDTH> ADD1;

void do_process1() { }
SC_CTOR(Cordic) : ADD1("ADD1") {
SC_METHOD(do_process1);
}
};

Unless your compiler supports the export keyword (it probably doesn't),
then Addsub() must be defined in each translation unit that uses it.
The easiest way to accomplish this is to make sure it appears in the
header file, whether in the class definition or by #including
addsub.cpp at the end of the header file.

Cheers! --M
 
T

Thomas Tutone

Hans said:
Hi All,

In the stripped down code example below Visual C++ 2005 issues the following
error:

error LNK2019: unresolved external symbol "public: void __thiscall
Addsub<24>::do_process123(void)"

This is a SystemC example, however I believe this is a basic C++ syntax
error since if I move the Addsub function inside the Addsub class (that is
delete File2) then all is OK so I must have made a mistake in the template
definition?

Thanks,
Hans.

// File 1 addsub.h
template <int ADDSUB_WIDTH=24>
SC_MODULE(Addsub)
{

void do_process123(); // fails
void do_process123() {}; // works, excl addsub.cpp

SC_CTOR(Addsub) {
SC_METHOD(do_process123);
}
};

// File 2 addsub.cpp
template <int ADDSUB_WIDTH>
void Addsub<ADDSUB_WIDTH>::do_process123(){}

// File 3 top.h
#include "addsub.h"

#define WIDTH 24

SC_MODULE(Cordic) {
public:

Addsub<WIDTH> ADD1;

void do_process1() { }
SC_CTOR(Cordic) : ADD1("ADD1") {
SC_METHOD(do_process1);
}
};

This is an FAQ:

http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12

Best regards,

Tom
 
H

Hans

This is an FAQ:

Thanks guys,

Unfortunately I still get an error. I have removed the SystemC stuff and
created a simple C++ example using the same template coding style as in the
FAQ, for some reason Visual C++ doesn't like the "simple template class"
solution, I did change the template<typename T> to template<int T> any idea?

// File "Foo.h"
template<int T>
class Foo {
public:
void g();
};

// File "Foo.cpp"
#include <iostream>
#include "Foo.h"
template<int T>
void Foo<T>::g()
{
std::cout << "T=" << T << std:endl;
}
template class Foo<int>; // Error C2975, without it LNK2019 Error

// File "main.cpp"
#include "Foo.h"
int main()
{
Foo<4> x;
x.g();
}

Hans.
 
T

Thomas Tutone

Hans said:
Thanks guys,

Unfortunately I still get an error. I have removed the SystemC stuff and
created a simple C++ example using the same template coding style as in the
FAQ, for some reason Visual C++ doesn't like the "simple template class"
solution, I did change the template<typename T> to template<int T> any idea?

// File "Foo.h"
template<int T>
class Foo {
public:
void g();
};

// File "Foo.cpp"
#include <iostream>
#include "Foo.h"
template<int T>
void Foo<T>::g()
{
std::cout << "T=" << T << std:endl;
}
template class Foo<int>; // Error C2975, without it LNK2019 Error

Change the above line to:

template class Foo<4>;

and it should work fine. See below for explanation.
// File "main.cpp"
#include "Foo.h"
int main()
{
Foo<4> x;
x.g();
}


Explanation: You can declare _either_ (a) template class Foo<int T>
_or_ (b) template class Foo<typename T>. Unfortunately, your code did
both - in one place defining it one way, the other place defining it
the other. My change above fixes that.

Best regards,

Tom
 
M

mlimber

Hans said:
Thanks guys,

Unfortunately I still get an error. I have removed the SystemC stuff and
created a simple C++ example using the same template coding style as in the
FAQ, for some reason Visual C++ doesn't like the "simple template class"
solution, I did change the template<typename T> to template<int T> any idea?

// File "Foo.h"
template<int T>
class Foo {
public:
void g();
};

// File "Foo.cpp"
#include <iostream>
#include "Foo.h"
template<int T>
void Foo<T>::g()
{
std::cout << "T=" << T << std:endl;

You meant std::endl.
}
template class Foo<int>; // Error C2975, without it LNK2019 Error


// File "main.cpp"
#include "Foo.h"
int main()
{
Foo<4> x;
x.g();
}

The same comments about putting implementations for templates in the
header apply, and in fact, everything links fine if you fix the two
above errors and make sure all this code is visible in a single
translation unit.

Cheers! --M
 
T

Thomas Tutone

mlimber said:
You meant std::endl.


This line is non-sense in context. You are instantiation Foo<> with a
type rather than a constant int.
True.


The same comments about putting implementations for templates in the
header apply, and in fact, everything links fine if you fix the two
above errors and make sure all this code is visible in a single
translation unit.

Actually, if one follows the explicit instantiation examples shown in
the FAQ, one does not need to put all the code in a single translation
unit. If the OP substitutes "template class Foo<4>;" for the line with
the error, it will work fine in separate translation units. I often
use the explicit instantiation trick to cut down on compilation times.

Best regards,

Tom
 
M

mlimber

Thomas said:
Actually, if one follows the explicit instantiation examples shown in
the FAQ, one does not need to put all the code in a single translation
unit. If the OP substitutes "template class Foo<4>;" for the line with
the error, it will work fine in separate translation units. I often
use the explicit instantiation trick to cut down on compilation times.

Right you are. I avoid that method, however, because it couples client
code to my template code, which is otherwise independent of it.

Cheers! --M
 
H

Hans

...
The same comments about putting implementations for templates in the
header apply, and in fact, everything links fine if you fix the two
above errors and make sure all this code is visible in a single
translation unit.

Cheers! --M

Hi Guys,

Thanks for the explanation, however, can I draw one more time on your
collective expertise by asking how I could change "4" into a compile time
constant. What I mean by that is that I would like to instantiate Foo with
different constant values:

//File Foo.cpp
template class Foo<?>;

// File "main.cpp"
#include "Foo.h"
int main()
{
Foo<4> x;
Foo<8> y;
x.g();
}

Of course I could go with the FAQ-35.12 solution 1 which works fine but I am
pretty sure that this issue will come back to haunt me :)

Thanks,
Hans.
 
T

Thomas Tutone

Hans said:
Thanks for the explanation, however, can I draw one more time on your
collective expertise by asking how I could change "4" into a compile time
constant. What I mean by that is that I would like to instantiate Foo with
different constant values:

//File Foo.cpp
template class Foo<?>;

You have to include an explicit instantiation for every constant value
that you will need - that's the downside of this method. So here, you
would need to include the following two lines:

template class Foo<4>;
template class Foo said:
// File "main.cpp"
#include "Foo.h"
int main()
{
Foo<4> x;
Foo<8> y;
x.g();
}

The alternative is to follow mlimber's advice and put the full
definition of the template in the header file.

Best regards,

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,165
Latest member
JavierBrak
Top