编写了一个模板类,例如,从内联模板的类型推断 sizeof。
BaseInformer.h
template<typename ValueType>
class BaseInformer {
private:
int size;
public:
BaseInformer();
virtual ~BaseInformer(){}
public:
virtual void printInfo();
void printValue(ValueType value);
public:
std::string getSize() const;
virtual std::string getName() const = 0;
};
extern template class BaseInformer<int>;
extern template class BaseInformer<char>;
BaseInformer.cpp
template class BaseInformer<int>;
template class BaseInformer<char>;
template<typename ReturnValue>
BaseInformer<ReturnValue>::BaseInformer() {
size=sizeof(ReturnValue);
}
template<typename ValueType>
void BaseInformer<ValueType>::printValue(ValueType value) {
std::cout << getName() << " " << value << "\n";
}
template<typename ValueType>
void BaseInformer<ValueType>::printInfo() {
std::cout << getName() << " " << getSize() << "\n";
}
template<typename ValueType>
std::string BaseInformer<ValueType>::getSize() const {
std::stringstream ss;
ss << size;
return ss.str();
}
类 IntInformer 和 CharInformer 继承自它并且具有几乎相同的内容:
IntInformer.h
class IntInformer : public BaseInformer<int> {
public:
IntInformer(){}
virtual ~IntInformer() override {}
public:
virtual std::string getName() const override;
};
IntInformer.cpp
std::string IntInformer::getName() const {
return "Int";
}
因此,下面是主要功能的部分
主文件
int main() {
...
std::cout << "template printInfo()\n";
IntInformer().printInfo();
CharInformer().printInfo();
...
}
上面的代码使用MinGW64编译运行成功,使用MSVC2019x64编译器编译成功。但是,当尝试在 macOS 上使用 CLang 进行构建时,会输出以下日志:
Undefined symbols for architecture x86_64:
"BaseInformer<char>::printValue(char)", referenced from:
_main in main.o
"BaseInformer<char>::printInfo()", referenced from:
vtable for BaseInformer<char> in baseinformer.o
vtable for CharInformer in charinformer.o
_main in main.o
"BaseInformer<char>::BaseInformer()", referenced from:
CharInformer::CharInformer() in main.o
"BaseInformer<int>::printValue(int)", referenced from:
_main in main.o
"BaseInformer<int>::printInfo()", referenced from:
vtable for BaseInformer<int> in baseinformer.o
vtable for IntInformer in intinformer.o
_main in main.o
"BaseInformer<int>::BaseInformer()", referenced from:
IntInformer::IntInformer() in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [cpp-template-header] Error 1
20:02:57: Процесс «/usr/bin/make» завершился с кодом 2.
请告诉我,如果您想在不依赖于各种支持的编译器的情况下进行构建(在 CLang 下运行此业务),使用模板语法的正确方法是什么?如果可能的话,我想保留头文件和源代码文件的划分。为方便起见,我在此处发布了该项目。
模板的显式实例化的定义必须遵循模板本身的定义。
类模板的显式实例化的定义也是其所有成员模板的显式实例化的定义。因此,类的显式实例化的定义通常应在其成员模板的定义之后指定。
如果模板类的某些成员在整个类的显式实例化定义出现的时候没有被定义,那么它们就不会被显式实例化。见http://eel.is/c++draft/temp.explicit#12
这正是您的案例中发生的情况:您的所有类方法都没有被显式实例化。因此,链接器没有找到它们。
移动针迹
到文件底部
BaseInformer.cpp