具有显式模板实例化的未解析的外部。什么是声明语法?

时间:2010-03-23 15:52:24

标签: c++ templates instantiation unresolved-external

这是一些简化的代码来演示我遇到的问题。

我有一个模板函数,我只希望编译某些固定的实例。

函数声明是:

// *** template.h ***
int square (int x);
double square (double x);

定义如下:

// *** template.cpp ***
#include "template.h"

// (template definition unusually in a code rather than header file)
template <typename T>
T square (T x)
{
    return x*x;
}

// explicit instantiations
template int square (int x);
template float square (float x);

并且,使用示例是:

// *** main.cpp ***

#include <iostream>
using namespace std;

#include "template.h"

int main (void)
{
    cout << square(2) << endl;
    cout << square(2.5) << endl;
}

尝试编译这会导致链接错误,大致如下:

  

main.obj:函数main

中引用的未解析的外部符号“int square(int)”

我理解问题所在:我的显式模板实例化的函数签名与头文件中的函数签名不匹配。

显式模板实例化的(转发)声明的语法是什么?我不希望转发声明模板定义,或将模板定义移动到头文件中。

对于它的价值,我确实有一个解决方法,即使用包装函数,将以下内容添加到上述文件中:

// *** template.cpp ***

// ...

// wrap them [optionally also inline the templates]
int square (int x) { return square<> (x); }
double square (double x) { return square<> (x); }

编译并按预期工作。然而,这对我来说似乎是个黑客。应该有比C ++和模板语法更优雅的东西。

非常感谢任何帮助或提示。

2 个答案:

答案 0 :(得分:5)

您需要在标题中声明函数模板:

template <typename T>
T square(T x);

如你所知,你在标题中声明了两个非模板函数,这些函数从未定义过。

答案 1 :(得分:1)

如果要从头文件中隐藏模板,则没有其他方法。你必须有包装器函数,因为int square (int x);template int square (int x);没有相同的名称,而C ++没有为你提供改变它的方法。

您可以查看how name mingling differs in Visual Studio作为示例。