my first effort with template functions...

...is producing a compile error. I've defined a function:

1
2
3
4
5
6
7
template <class R> void UtilGain::cycle(
					R	gainInpI,
					R	gainInpQ,
					long	hostGain,
				    bool	clockEnable,
				    bool	resetFlag)
{...}


and I attempt to call it like this:

1
2
3
4
5
6
		gain.cycle<int64_t>
				(stage.at(LAST_CIC_COMB_STAGE).getIOut,
				 stage.at(LAST_CIC_COMB_STAGE).getQOut,
				 pSoc->modHost.getValue(MOD_HOSTCICGAIN),
				 clockEnable,
				 resetFlag);


I get the following error message:

n member function 'void ModCicComb::cycle(int64_t, int64_t, bool, bool)':
../modciccomb.cpp:57: error: no matching function for call to 'UtilGain::cycle(<unresolved overloaded function type>, <unresolved overloaded function type>, long int, bool&, bool&)'


What am I doing wrong? Is the template unable to work with the int64_t type? Thanks.
What you want to do is something like this:

1
2
3
4
5
6
7
8
UtilGain<int64_t> gain;      //default ctor assumed ( or you can substitute for the apt ctor)

//calling cycle function:
gain.cycle (stage.at(LAST_CIC_COMB_STAGE).getIOut,
		  stage.at(LAST_CIC_COMB_STAGE).getQOut,
		  pSoc->modHost.getValue(MOD_HOSTCICGAIN),
		  clockEnable,
		  resetFlag);
I'm not sure I understand this. As you probably deduced, gain is an object of type UtilGain. It's defined in the include file of the including object. So, where should the first line in your code go: in the constructor for the including class?
If i understand correctly, another object needs the functionality provided by UtilGain::cycle and that 's why it's being included. Should that be the case, then within the function body where cycle is to be used, a UtilGain object first needs to be instantiated with the requisite constructor before being called as i demonstrated.
Long shot
1
2
//stage.at(LAST_CIC_COMB_STAGE).getIOut
stage.at(LAST_CIC_COMB_STAGE).getIOut() //<- it is a method 
Aargh. You got it, ne555...sloppy work on my part.

I am now getting a link-time error, though.

Undefined symbols:
"void UtilGain::cycle<long long>(long long, long long, long, bool, bool)", referenced from:
ModCicComb::cycle(long long, long long, bool, bool)in modciccomb.o


Let me provide a bit more detail. The gain object is part of another object, ModCicComb. the relevant portion of the modciccomb.h file looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
#include "utilgain.h"
.
.
.
class	ModCicComb
{
	Soc* pSoc;
	vector<ModCicCombStage> stage;
	UtilGain	gain;
.
.
.


The call to gain.cycle is made from a member function of modciccomb (this function is also called cycle).

So, the UtilGain object is indeed instantiated within the ModCicComb object, and is "visible" to the cycle routine, but...something is missing.
Last edited on
If it is a template function, it needs to be in the .h(pp) file, not the .cpp.
Hi, firedraco. I'm not sure what "it" you're referring to.

Here's a snippet from the utilgain.h file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class UtilGain

{
	SocReg	a, b, c, d, e;
public:
	UtilGain(long rv=0);					//  constructor
	UtilGain (const UtilGain &ug);			// copy constructor
	~UtilGain();							// destructor
	//	void cycle(
		template <class R> void cycle (
		R		gainInpI,
		R		gainInpQ,
		long		hostGain,
		bool		clockEnable,
		bool		resetFlag);
}


Here's from the utilgain.cpp file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <UtilGain.h>

using namespace std;

UtilGain::UtilGain(long reset) // constructor w/ reset parameter
	: a(reset), b(reset), c(reset), d(reset), e(reset) {}

UtilGain::UtilGain 	// copy constructor
(const UtilGain &ug)
	: a(ug.a), b(ug.b), c(ug.c), d(ug.d), e(ug.e) {}
UtilGain::~UtilGain() {}	// destructor

//void UtilGain::cycle(
template <class R> void UtilGain::cycle(
					R	gainInpI,
					R	gainInpQ,
					long	hostGain,
				    bool	clockEnable,
				    bool	resetFlag)
{ ...


Is this not as it should be?

Thanks.
You can't have the template definition (lines 14 and beyond) in the .cpp file. Move it to the .h file.
Wow...well, that seems to have solved the build problem. So...template functions can't go into compilable files? What about template classes?

Thanks.
OK...my situation is a bit more complicated than I thought. I'm trying to define a template function to support two classes of my creation. One represents a 32-bit register, and the other, a 64-bit register.

The rub is, many of the functions (including a constructor) take input data types dependent upon the class: the 32-bit register takes longs, while the 64-bit register takes input of type int64_t.

So...this (for example) was wrong:

1
2
3
4
5
6
7
template <class R> void UtilGain::cycle(
					R	gainInpI,
					R	gainInpQ,
					long	hostGain,
				    bool	clockEnable,
				    bool	resetFlag)
{ ...


gainInpI and gainInpQ should be long if R is a 32-bit register, and int64_t if R is a 64-bit register. Is there a way to accomplish this?

Thanks.
1
2
3
4
5
6
7
template <class R, class S> void UtilGain::cycle(
					R	gainInpI,
					S	gainInpQ,
					long	hostGain,
				    bool	clockEnable,
				    bool	resetFlag)
{ ...
kfmfe: I guess my explanation wasn't clear -- gainInpI and gainInpQ will be the same as each other, just not the same as the type of the class.

But I think this solution is on the right track. Instead of "class S" can I pass the input type?
All templates get you is copying the type basically. You can't use them to do something like "If type T is an int, I want a double".
So...no way to have inputs to functions vary based upon the type?
No. Although I'm wondering why you need that kind of functionality. Couldn't you just make gainInpI and Q long long ints (or whatever) always then just truncate it when you put it in the register?
Maybe that would work. The UtilGain class is going to be used by various other objects, some of which will have 32-bit registers and some 64. Won't the linker give me an error if I try to pass a long to a function expecting a long long?

EDIT: I tried it, and it built OK. I guess I don't remember the C++ rules of type conversion as well as I thought.
Last edited on
You can't use them to do something like "If type T is an int, I want a double".


Um...what ever happened to template specializations?
Last edited on
Er. Yeah, you *can* do that. Then you have to overload all the things you want manually. Major screw-up on my part there...

But anyway, I would still suggest making them long long ints by default unless you really need a template.

As for:
Won't the linker give me an error if I try to pass a long to a function expecting a long long?


1) The compiler is what checks that, not the linker.
2) No, that is a promotion, which is always legal. (like short -> int, int -> double, etc).
Thanks for the clarification. I will take your suggestion; I can't see that it won't work.

One more question before I put this to bed: in a line such as this:

template <class R> void UtilGain<R>::cycle(

What does the "<R>" after UtilGain mean? Haven't I already identified the placeholder for the class/function?

Thanks again.
Topic archived. No new replies allowed.