8
votes

The following code declares a template, declares an explicit instantiation definition, then declares an explicit instantiation declaration:

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;
}

gives an error:

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

in Visual Studio 2012.

I'm under the impression from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm that this should be valid, since the definition follows the declaration.

Am I missing something?

3

3 Answers

7
votes

Your program is well-formed. Paragraph 14.7.2/11 of the C++11 Standard specifies:

If an entity is the subject of both an explicit instantiation declaration and an explicit instantiation definition in the same translation unit, the definition shall follow the declaration. [...]

Your program respects this constraint and does not break any other rule. Therefore, this qualifies as a bug in VC11.

3
votes

It seems this issue was reported to Microsoft Connect 620017:

Posted by Microsoft on 12/3/2010 at 1:52 PM

Hello,

As you've noted, our implementation of extern templates does not conform to the C++-0x standard. We still have our old extension implementation. Although we don't have the resources to implement the C++-0x version of this feature for the next release of Visual Studio, conformance issues are a priority for us; we do currently intend to implement this feature in a future version of Visual Studio.

Thanks for taking the time to report this issue. We do appreciate it.

Jamie Eckman Visual C++ Team

That was from 2010, so by "next release" he meant VS2012.

3
votes

This Visual C++ conformance bug is addressed in Visual Studio 2013, which is available here. This fix makes it possible to place extern template declarations in header files to suppress template instantiation and still declare an explicit instantiation in one module, which can cut down on compilation time and code bloat. Reversing the statements (that is, an explicit instantiation request, followed by an extern template declaration with the same template arguments) still causes error C2929, since it looks like you are now trying to suppress something you've already explicitly instantiated.