1

I'm working on this NeuralNet class:

class NeuralNet {
public:
    // Public functions
private:
    vectors vect; // Point-of-access for functions in class vectors
    // Private functions
};

And I'm using this extremely simple makefile:

all: nnet.exe
nnet.exe: main.o neuralnet.o vectors.o
    g++ -o nnet.exe main.o vectors.o neuralnet.o
main.o: main.cpp neuralnet.h
    g++ -ggdb -c main.cpp
vectors.o: vectors.cpp vectors.h
    g++ -ggdb -c vectors.cpp
neuralnet.o: neuralnet.cpp neuralnet.h vectors.h
    g++ -ggdb -c neuralnet.cpp
clean:
    rm -f *.o nnet.exe

When g++ gets run to build the final executable, I get a lot of errors in the following form:

neuralnet.o: /path/to/neuralnet.cpp: line# : undefined reference to vectors::fn_name(args)

For example, I have defined a function:

template<typename T> void fill_vec(vector<T>&, int, double);

When I call this function I pass a variable declared with type vector<double> for the first argument, and the linker reports undefined reference to void vectors::fill_vec<double>(std::vector<double, std::allocator<double> >&, int, double)

All calls to functions of class vectors in the implementation of NeuralNet are called from vect. However, both neuralnet.cpp and neuralnet.h contain includes for "vectors.h", so I'm assuming that I'm somehow linking incorrectly.

Does anyone see anything obvious?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Rob
  • 5,223
  • 5
  • 41
  • 62
  • Do you have vectors.h included in neuralnet.h? – Kizaru Mar 07 '11 at 05:22
  • Yes, the neuralnet header also has an include for vectors.h. Editing question to reflect now. – Rob Mar 07 '11 at 05:27
  • This is going to sound stupid - fn_name() (cAsE sEnSiTiVe) is being used properly right? After this error, you don't receive a "candidates are..." message or anything do you? This isn't a linking issue by the way. the `g++ -c` parameter takes away linking until your final step. – RageD Mar 07 '11 at 05:43
  • @RageD, the file name g++ mentions is a .o file, and the error message is "undefined reference" — it's definitely a linking issue. – Rob Kennedy Mar 07 '11 at 05:54
  • @RageD - no, not any messages about candidate functions. Also, the question says that the errors occur when g++ is being used to build the final executable from the object files, which is when linking should occur. – Rob Mar 07 '11 at 05:55
  • Ah, sorry - my mistake read through too quickly – RageD Mar 07 '11 at 06:18

1 Answers1

2

Unless you've defined fn_name() in-line in vectors.h, merely including that header from neuralnet.cpp and neuralnet.h is not sufficient. Make sure you can actually point your finger at that function body. You probably intended for it to be in vectors.cpp.

Being a template changes everything. You should define the template methods in the header file, not in the .cpp file. Although you might define fill_vec<T> in your source file, the compiler doesn't actually instantiate it for any values of T because within that translation unit, it doesn't need any instantiations. You could manually instantiate it for every value of T you'll need, but it's easier to just define the function in the header at the same place you declare it. That way, the compiler has the definition available every place it's needed. You'll get multiple instantiations (one for each translation unit that uses it), but the linker knows how to consolidate those.

See also Undefined reference error for template method.

Community
  • 1
  • 1
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • The variations of `fn_name()` appearing in the error messages are all defined in *vectors.cpp*, which of course also includes vectors.h -- what do you mean when you say point my finger at the function body? – Rob Mar 07 '11 at 05:58
  • 2
    I mean you should make sure you can actually find the variation the linker says is missing. Is the zero-argument version of the function really defined? What line is it defined on? I'm going on the assumption that the linker is telling the truth, and that the function isn't really defined. If you think it *is* defined, prove it. If you can't point your finger at it and say, "This is where it's defined," then it's not defined. Also make sure you don't have any `ifdef` instructions that might have caused the compiler to skip over that function. – Rob Kennedy Mar 07 '11 at 06:31