0

I have a small C++ project whose structure looks like this

  • build
    • obj
    • makefile
  • include
    • utils.h
  • src
    • utils.cpp
    • main.cpp

The header files contains custom types and multiple functions' declarations like so

#pragma once
#include "utils.h"

...

#include <boost/math/constants/constants.hpp>
#include <gsl/gsl_poly.h>

typedef boost::multiprecision::float128 float128;
typedef boost::multiprecision::mpf_float_1000 float1k;

template<typename type>
int compute_n(const type& lambda_max, const type& lambda_min);

template<typename type>
float1k compute_estimate(const type& input_lambda, const int& num_nodes, const std::string& envelope);

...

Their definitions are implemented in utils.cpp. In main.cpp the functions are called like so

#include "utils.h"

int main(int argc, char** argv)
{

    float128 lambda_max = 1.0, lambda_min = 2.0;
    
    ...

    int n_nodes = compute_n(lambda_max, lambda_min);

    ...

My makefile is simple

CXX = g++

INCDIR = ../include
SRCDIR = ../src
OBJDIR = obj

OBJ = $(OBJDIR)/main.o $(OBJDIR)/utils.o

CXXOPTIONS = -g #-Wall
CXXFLAGS = $(CXXOPTIONS) -I $(INCDIR) 

LDLIBS = -lm -lgsl -lgslcblas -lgmp -lquadmath
LDFLAGS = $(LDLIBS)

default: $(OBJ)
    $(CXX) $^ -o HiSink $(LDFLAGS)

$(OBJDIR)/main.o: $(SRCDIR)/main.cpp $(SRCDIR)/utils.cpp $(INCDIR)/utils.h
    $(CXX) -c $< -o $@ $(CXXFLAGS)

$(OBJDIR)/utils.o: $(SRCDIR)/utils.cpp $(INCDIR)/utils.h
    $(CXX) -c $< -o $@ $(CXXFLAGS)

clean:
    rm -f $(OBJDIR)/*.o HiSink

Both source files are compiled and object files are created. At link time however I get an undefined reference for one specific function, that is compute_n which I left in the scripts above on purpose. The error is

/usr/bin/ld: obj/main.o: in function `main':
/home/path-to-main/main.cpp:30: undefined reference to `int compute_n<double>(double const&, double const&)'
collect2: error: ld returned 1 exit status

Even weirder is that if I "move" the definition of compute_n in main.cpp the issue disappears, the linker doesn't complain and the executable is created and runs correctly.

I want to stress on the fact that I have multiple (6) functions declarations in utils.h and all their definitions are in utils.cpp yet the only one that does this little trick is compute_n.

Can anyone shed some light here (I am a begineer in C++) ?

  • Not really, unless I am missing something obvious here. The other functions also use templates yet only this one gets the linker to complain. – Davide Papapicco Sep 17 '21 at 10:06
  • 1
    When you compile the file where `int compute_n(...)` is defined there is nothing triggering an instantiation of that template. Think about it. If you make a library with template functions, what instantiations of the template functions should be put inside the library? `int compute_n`, `int compute_n`, `int compute_n`, ... you name it. No... instead, **no** instantiations are compiled into the library - unless you instantiate them **explicitly** (which is rarely what you want). – Ted Lyngmo Sep 17 '21 at 10:24
  • 1
    related stuff is discussed here ... maybe this helps [link]https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl – dorKKnight Sep 17 '21 at 10:30
  • 1
    @TedLyngmo thanks, that pretty much explains it all and yes, it is obvious if one thinks about it. Thank you very much. – Davide Papapicco Sep 18 '21 at 08:52

0 Answers0