我有以下Makefile来制作我的项目:
# 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包含Connector.h,Connector.cpp实现Connector.h中声明的函数。一切都很好,直到连接阶段。
现在当我运行它时,输出如下:
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 */
如果您需要源文件请注释,我认为没必要(是的,所有函数等都是声明的,如果我包含Connector.cpp而不是Connector.h一切都很好)
我的规格是:Eclipse M4.3,gcc版本4.8.0
答案 0 :(得分:1)
此编译错误与模板实例化有关。要解决此问题,可以将类Connector
的实现放入头文件中。
此answer对原因给出了非常好的解释,请查看。
答案 1 :(得分:1)
大多数编译器都需要在源文件中定义模板Connector
(或者在源文件中重新声明模板类)
在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) {}
};