• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3222
  • Last Modified:

Undefined reference to defined constructor?

I'm having a problem with a C++ project I'm working on. The relevent portion tries to create a templated object by calling its constructor and passing in a vector of ints. But when I try to link I get this error:

objs/clock.o: In function `main':
clock.cpp:48: undefined reference to `Solver<ClockConfiguration>::Solver(std::vector<int, std::allocator<int> >)'
collect2: ld returned 1 exit status

Here are the relevent code sections:

clock.cpp:
#include <iostream>
#include <vector>
#include "SolverConfiguration.h"
#include "ClockConfiguration.h"
#include "Solver.h"

int main(int argc, char** argv) {
  int hours, ctime, rtime;
...
  std::vector<int> data;
  data.push_back(hours);
  data.push_back(ctime);
  data.push_back(rtime);
 
  Solver<ClockConfiguration> solver(data); // This is the line that errors
}

Solver.h:
#ifndef H_SOLVER_INTERFACE
#define H_SOLVER_INTERFACE

#include <queue>

template <class T>
class Solver {
 public:
  Solver(std::vector<int> data);
}
#endif

Solver.cpp:
#include "Solver.h"
#include <string>

template<class T>
Solver<T>::Solver(std::vector<int> data) {
  start = T(data);
  end = start.makeEnd();
}


I don't get what's wrong. The necessary constructor is there, and g++ sees them and compiles fine with no warnings.
0
firejdl
Asked:
firejdl
  • 3
  • 3
1 Solution
 
jkrCommented:
The problem is that you put the constructor in a separate source file. Even though the C++ standard allows that, hardly any compiler supports it. Add a

#include <iostream>
#include <vector>
#include "SolverConfiguration.h"
#include "ClockConfiguration.h"
#include "Solver.h"
#include "Solver.cpp" // <----

as a workaround. Yes, this is ugly, but to this time the only way to solve the problem (no pun intended).
0
 
jkrCommented:
BTW: You of course can also put the #include statement at the end of Solver.h or place the implementation code in that file in the 1st place.
0
 
firejdlAuthor Commented:
Thanks for the advice jkr, but that just seemed to make it worse. I tried it both with #include "Solver.cpp" and placing the implementation code in the Solver.h file, but now I'm getting compiler errors:

Solver.cpp:20: error: no matching function for call to 'ClockConfiguration::ClockConfiguration()'
ClockConfiguration.h:19: note: candidates are: ClockConfiguration::ClockConfiguration(std::vector<int, std::allocator<int> >)
ClockConfiguration.h:18: note:                 ClockConfiguration::ClockConfiguration(int, int, int, int)
ClockConfiguration.h:16: note:                 ClockConfiguration::ClockConfiguration(const ClockConfiguration&)
Solver.cpp:20: error: no matching function for call to 'ClockConfiguration::ClockConfiguration()'
ClockConfiguration.h:19: note: candidates are: ClockConfiguration::ClockConfiguration(std::vector<int, std::allocator<int> >)
ClockConfiguration.h:18: note:                 ClockConfiguration::ClockConfiguration(int, int, int, int)
ClockConfiguration.h:16: note:                 ClockConfiguration::ClockConfiguration(const ClockConfiguration&)
clock.cpp:48:   instantiated from here
Solver.cpp:23: error: no match for 'operator=' in '((Solver<ClockConfiguration>*)this)->Solver<ClockConfiguration>::end = ((Solver<ClockConfiguration>*)this)->Solver<ClockConfiguration>::start. ClockConfiguration::makeEnd()'
ClockConfiguration.h:16: note: candidates are: ClockConfiguration& ClockConfiguration::operator=(const ClockConfiguration&)
make: *** [objs/clock.o] Error 1


Now, ClockConfiguration does NOT have a default constructor, so that portion is normal. But where is it calling ClockConfiguration::ClockConfiguration you ask? Apparently, in the line:

Solver<T>::Solver (std::vector <int> data) {

When I space this out on seperate lines, it seems to be caused by the ) for some reason. Is this because when I use ClockConfiguration as T, the ClockConfiguration needs to be instantiated too somehow? Should Solver do that?
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
jkrCommented:
>>But where is it calling ClockConfiguration::ClockConfiguration you ask?

A lot of STL containers copy objects internally or create temp. instances, that is likely to be the reason why a default constructor is required. Anyway, it is always a good idea to provide one.
0
 
firejdlAuthor Commented:
What STL container is holding ClockConfiguration objects on that line? The vector there is holding ints. That's what is confusing to me: that nothing really needs to call a constructor for a ClockConfiguration object.

But anyway, thanks for your help. I've got it working now and just need to finish the project.
0
 
firejdlAuthor Commented:
By the way, it doesn't seem to matter whether the function called is the constructor or not. When I created a function called setData(std::vector<int> data) and implemented it in the .cpp file, and did not #include the .cpp file anywhere, I was welcomed by the exact same ld error.
0
 
Infinity08Commented:
>> I was welcomed by the exact same ld error.

Templates are weird animals ;)
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now