8

以下代码声明一个模板,声明一个显式实例化定义,然后声明一个显式实例化声明:

template <typename T>
T Double(T number)
{
    return number * 2;
}

extern template int Double<int>(int);  // declaration
template int Double<int>(int t);       // definition

int main(int argc, char* argv[])
{
    int n = Double(10);

    return 0;
}

给出一个错误:

error C2929: 'int Double<int>(int)' : explicit instantiation; cannot explicitly force and suppress instantiation of template-class member

在 Visual Studio 2012 中。

我对http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm的印象是这应该是有效的,因为定义遵循声明。

我错过了什么吗?

4

3 回答 3

7

您的程序格式正确。C++11 标准的第 14.7.2/11 段规定:

如果一个实体是同一翻译单元中的显式实例化声明和显式实例化定义的主体,则定义应遵循声明。[...]

您的程序尊重此约束并且不违反任何其他规则。因此,这被认为是 VC11 中的错误。

于 2013-05-28T17:26:38.237 回答
3

似乎此问题已报告给Microsoft Connect 620017

Microsoft 于 2010 年 12 月 3 日下午 1:52 发布

你好,

正如您所指出的,我们对 extern 模板的实现不符合 C++-0x 标准。我们仍然有旧的扩展实现。尽管我们没有资源为 Visual Studio 的下一个版本实现此功能的 C++-0x 版本,但一致性问题是我们的首要任务;我们目前确实打算在未来版本的 Visual Studio 中实现此功能。

感谢您花时间报告此问题。我们很感激。

Jamie Eckman Visual C++ 团队

那是从 2010 年开始的,所以“下一个版本”是指 VS2012。

于 2013-06-18T12:02:36.487 回答
3

此 Visual C++ 一致性错误已在 Visual Studio 2013 中得到解决,可在此处获得。此修复可以将extern template声明放在头文件中以抑制模板实例化,并且仍然在一个模块中声明显式实例化,这可以减少编译时间和代码膨胀。反转语句(即,显式实例化请求,后跟extern template具有相同模板参数的声明)仍会导致错误 C2929,因为您现在似乎正试图抑制已显式实例化的某些内容。

于 2013-09-24T19:50:29.307 回答