views:

42

answers:

3

Hi,

I am facing a few problems with "undefined reference to " errors. I may not be able to post the code, but the declarations and the way I am calling the functions are as follows:

Declarations:

template <typename T>
int pitch_detect(deque<T>& x, int offset, int len);

template <typename T>
int is_voiced(
  deque<T>& x, int offset, int len,
  double avg_energy, int pre_voice,
  short& s_flag,
  long nsamples
);

I am calling the above functions as follows:

x = is_voiced(superFrame_, cur_offset_, f_len_,
    avgEnergy_, frame_voicing_[1], silence_flag_, nsamples_);

y = pitch_detect(superFrame_, cur_offset_, f_len_);

The above statements (where I am calling the functions), get flagged as errors. These are the messages:

undefined reference to `int is_voiced(std::deque >&, int, int, double, int, short&, long)

undefined reference to `int pitch_detect(std::deque >&, int, int)'

Any help in decoding the above errors is most welcome. Thanks, Sriram

Edit: The above functions are defined in a separate header and corresponding C++ file. I get no problems when I try to compile them and create an object file. These errors are seen in the linker stage.

+1  A: 

Put the definitions of the functions in the header file, instead of in a separate CPP file; and, in the header file, prefix the function definitions with the inline keyword, to avoid the linker complaining about duplicate definitions.

ChrisW
+1  A: 

I haven't tried g++, but have you tried explicitly naming the type?

x = is_voiced<PutTypeNameHere>(superFrame_, etc);

Are the definitions and calling done from the same dll/exe? If not, you may need to explicitly instantiate the template functions with the types you're calling them with.

Scott Langham
I had not explicitly instantiated the template functions. That was the problem. THanks scott!
Sriram
+2  A: 

Have you provided definitions for those templates? Are you explicitly instantiating the templates yourself or allowing the compiler to instantiate them?

If you provide a template declaration but the compiler does not see the definition in the same translation unit, it will assume that the template will be instantiated in another translation unit, and will just generate the call, but not compile (without seeing the definition it cannot possibly do it) the specific instantiation. Later at link time the linker will see the call, but will not see the instantiation and will fail with the undefined reference error.

The simplest solution is just having the template declaration and definition together:

template <typename T>
int is_voiced( deque<T>& x, int offset, int len, double avg_energy, int pre_voice, short& s_flag, long nsamples ) 
{
  // code here
}

Then when you use is_voiced(...) the compiler will implicitly instantiate the template for you (it sees the code, and it will compile it).

There are a few cases where you do not want the compiler to implicitly instantiate your templates (you know what types are going to be used, and you do not want the compiler to allow other uses --or it is expensive to compile and want to speed compilation up by only instantiating the templates in a single translation unit). For those cases you will need to provide your own explicit instantiation in a translation unit.

// header
template <typename T>
int is_voiced( deque<T>& x, int offset, int len, double avg_energy, int pre_voice, short& s_flag, long nsamples ); 

// cpp
template <typename T>
int is_voiced( deque<T>& x, int offset, int len, double avg_energy, int pre_voice, short& s_flag, long nsamples ) {
   // code goes here
}
// explicit instantiation for int
template int is_voiced( deque<int>& x, int offset, int len, double avg_energy, int pre_voice, short& s_flag, long nsamples );

Then compile that implementation file and link it with the rest of the project.

Note: it is advisable to provide the full template definition in the header so that the compiler can implicitly instantiate it, unless you have a good reason not to do so.

David Rodríguez - dribeas
Ah! Yes. That was the problem. I had not explicitly instantiated the templates. I am new to templates and have a LOT to learn. Problem solved! Thanks David!
Sriram
Do you really need to use explicit instantiation? In most cases it is better just providing the definition of the template in the header and having the compiler implicitly instantiate it on usage.
David Rodríguez - dribeas