我有两个模板类,Leaf<T>
源自 Base<T>
, 然后我开发了一个模板函数,它使用了 Base<T>
的引用作为它的参数。并在其源文件中设置该函数的定义和实例化。
问题发生在我试图通过 Leaf<T>
时作为该函数的参数。编译器尝试使用 Leaf<T>
查找符号没有像过去那样的自动约定。
// foo.h
#ifndef __FOO_H_INCLUDED__
#define __FOO_H_INCLUDED__
#include <base.h>
template <typename T>
void Foo(T &value);
#endif // __FOO_H_INCLUDED__
// foo.cpp
#include <foo.h>
#include <iostream>
template <typename T>
void Foo(T &value)
{
std::cout<<value.getValue()<<std::endl;
}
template void Foo(MyBase<int> &value);
// main.cpp
#include <leaf.h>
#include <foo.h>
int main()
{
int i = 20;
MyLeaf<int> leaf;
leaf.setValue(i);
Foo(leaf);
}
上面的代码片段将在链接中抛出“ undefined reference ”异常。将调用重构为 Foo<MyBase<int> >(leaf)
将解决问题,但这不是我想要的。并且显式实例化所有潜在的派生类型也是不可能的,因为无法知道它们有多少。
那么有没有一种方法可以让链接器识别我的基本类型的符号,而不是找到准确的符号并抛出错误?
最佳答案
在一个翻译单元中添加显式模板实例化必须与显式模板实例化声明配对,以确保编译器不会尝试进行隐式实例化。否则,程序是病式的。
除此之外,模板参数推导不能推导除 Foo<MyLeaf<int>>
以外的任何内容。你设置它的方式。但是通过一些调整,我们可以让它工作。在你的标题中:
template <typename T>
void Foo(MyBase<T> &value);
extern template void Foo(MyBase<int> &value);
在你的实现文件中:
template <typename T>
void Foo(MyBase<T> &value)
{
std::cout<<value.getValue()<<std::endl;
}
template void Foo(MyBase<int> &value);
现在推导规则和重载决策应该正确匹配函数。我们所做的是转移负担。现在该函数总是需要一个从 MyBase
实例化的类.并且由于每个类都是从 MyLeaf
实例化的也派生自 MyBase
实例化的一个,你看它去了哪里。我们满足了参数的模板要求,让它去推导T
。从中。
关于c++ - 调用模板显式实例化时如何开启自动匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48350570/