Undefined reference to own files

I have the following Makefile to make my project:

# can be set by the user
LD_FLAGS ?= $(if $(GENERATE_EXECUTABLE),,-shared)
LIBS_FLAGS ?=
INCLUDE_FLAGS ?=
CXX_FLAGS ?= -O3 -Wall -std=c++11

objects = Connector.cpp main.cpp
defines := $(objects:.o=.def)
-include $(defines)
# main target
bin/o.exe: $(objects)
    @echo '[LD] $^ > $@'
    $(CXX) $(LD_FLAGS) $^ -o $@ $(LIBS_FLAGS)

define generate_def
echo '[DEF] $< > $@'
$1 -MM $(INCLUDE_FLAGS) $2 $< > $@
mv -f $@ $@.tmp
sed -e 's|.*:|$@:|' < $@.tmp > $@
sed -e 's/.*://' -e 's/\\$$//' < $@.tmp | fmt -1 | \
    sed -e 's/^ *//' -e 's/$$/:/' >> $@
rm -f $@.tmp
endef
# Compile C++-Files with an appropriate def-file
obj/c++/%.def: %.cpp
    @$(call generate_def,$(CXX),$(CXX_FLAGS))
$(objectscxx): obj/c++/%.o: %.cpp obj/c++/%.def # C++-Files
    @echo '[CXX] $< > $@'
    $(CXX) -c $< $(INCLUDE_FLAGS) $(CXX_FLAGS) -o $@

all: bin/o.exe

main.cpp includes Connector.h and Connector.cpp implements the function declared in Connector.h. Everything compiles fine until the linking stage.

Now when I run it the output is the following:

make all
[DEF] src/main.cpp > obj/c++/src/main.def
[DEF] src/Connector.cpp > obj/c++/src/Connector.def
[CXX] src/Connector.cpp > obj/c++/src/Connector.o
g++ -c src/Connector.cpp -O3 -Wall -g -std=c++11 -o obj/c++/src/Connector.o
[CXX] src/main.cpp > obj/c++/src/main.o
g++ -c src/main.cpp -O3 -Wall -g -std=c++11 -o obj/c++/src/main.o
[LD] obj/c++/src/Connector.o obj/c++/src/main.o obj/res/test.txt.o > bin/o.exe
g++ -static obj/c++/src/Connector.o obj/c++/src/main.o obj/res/test.txt.o -o bin/o.exe 
obj/c++/src/main.o: In function `SpecialConnector::~SpecialConnector()':
C:\Users\Carbon\Documents\Eclipse-Workbench\EpicRPG/src/main.cpp:35: undefined reference to `engine::Connector<SpecialReceiver>::~Connector()'
/**
* More undefined references
*/
obj/c++/src/main.o:C:\Users\Carbon\Documents\Eclipse-Workbench\EpicRPG/src/main.cpp:35: more undefined references to `engine::Connector<SpecialReceiver>::~Connector()' follow
collect2.exe: error: ld returned 1 exit status
make: *** [bin/o.exe] Error 1

Connector.h

/*
 * Connector.h
 *
 *  Created on: 03.06.2014
 *      Author: Carbon
 */

#pragma once
#ifndef CONNECTOR_H_
#define CONNECTOR_H_

#include <type_traits>

namespace engine
{
template<typename DataType, typename ConnectorType>
struct DefaultReceiver {
public:
    DefaultReceiver() {

    }
    virtual ~DefaultReceiver() {

    }

    static const char* receive(DataType data, ConnectorType conn, void* options) {
        return "b";
    }
};

template<template<typename, typename> class Receiver = DefaultReceiver>
class Connector
{
public:
    Connector();
    virtual ~Connector();

    template<typename DataType, typename ConnectorType>
    std::enable_if<true, const char*>::type
    receive(DataType i, ConnectorType c, void* o);
};

} /* namespace engine */
#endif /* CONNECTOR_H_ */

Connector.cpp

/*
 * Connector.cpp
 *
 *  Created on: 03.06.2014
 *      Author: Carbon
 */

#include "Connector.h"

namespace engine
{
template<template<typename, typename> class Receiver>
Connector<Receiver>::Connector()
{
    // TODO Auto-generated constructor stub

}
template<template<typename, typename> class Receiver>
Connector<Receiver>::~Connector()
{
    // TODO Auto-generated destructor stub
}

template<template<typename, typename> class Receiver>
template<typename DataType, typename ConnectorType>
std::enable_if<true, const char*>::type
Connector<Receiver>::receive(DataType input, ConnectorType connector, void* options) {
    return Receiver<DataType, ConnectorType>::receive(input, connector, options);
}
} /* namespace engine */

If you need source-files please comment, I don't think it's necessary (yes, ALL functions etc. are declared, if I include Connector.cpp instead of Connector.h everything is fine).

My specs are: Eclipse M4.3, gcc version 4.8.0

Answers


This compile error is regards to template instantiating. To solve this problem, you can put the implementation of Class Connector into the header file.

This answer gives a very good explanation on the reason, please check it out.


Most compilers will need the definition of your template Connector in your source file (or alternatively a redeclaration of the template class in the source file)

in particular, the constructor and the destructor should be defined (only declared) in the header file.

In Connector.h :

template<template<typename, typename> class Receiver = DefaultReceiver>
class Connector
{
public:
    Connector() {}
    virtual ~Connector() {}

    template<typename DataType, typename ConnectorType>
    std::enable_if<true, const char*>::type
    receive(DataType i, ConnectorType c, void* o) {}
};

Need Your Help

Batch: checking commandline parameters in batch file

loops batch-file parameters cmd

I want to do some actions in a DOS batch file depending on the incoming command line parameters.

Summing duplicate values while reading in data

c# asp.net streamwriter

I am reading in 5000 rows of data from a stream as follows from top to bottom and store it in a new CSV file.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.