4

I want to declare specialization for function template, but define it later in source file. Consider next example:

.hpp

// approach #1
template <typename T> const char *GetTypeName();
template <> const char *GetTypeName<int>();

// approach #2
template <typename T> class TypeName {static const char *Get();};
template <> const char *TypeName<int>::Get();

.cpp

// approach #1
template <> const char *GetTypeName<int>()
{
    return "int"
}

// approach #2
template <> const char *TypeName<int>::Get()
{
    return "int"
}

In MSVC 2012 (CTP is not installed), both variants compile fine, but nonmember variant (#1) raises linker errors (unresolved externals, blah). Is it normal behaviour? MSVC specific? Compiler bug? Fixed in CTP?

EDIT
I am using specialized versions only. They are declared in headers and defined in sources. This approach works for members, but does not works for standalone functions.

EDIT 2
Hmm... I'm trying to build same snapshot at home (identical MSVC installation, no CTP), and it links without issues. Seems like local bug or corrupted installation.

Shadows In Rain
  • 1,140
  • 12
  • 28
  • Unresolved externals for the specializations, or what? Are the uses in the same DLL, or a different DLL? – James Kanze Apr 24 '13 at 22:50
  • @JamesKanze Unresolved externals for nonmember specializations. I'm using only specialized versions. Standalone application, no DLLs. – Shadows In Rain Apr 24 '13 at 22:54
  • And the source file with the implementation of the specializations is part of the project? – James Kanze Apr 24 '13 at 23:08
  • Could you edit your question to contain a complete example which doesn't work? I've often done similar things (but perhaps not exactly the same), and it's always worked (both with MSVC and g++). – James Kanze Apr 24 '13 at 23:10
  • @JamesKanze Thank you for your efforts. Problem solved. See last update. – Shadows In Rain Apr 24 '13 at 23:47

1 Answers1

3

A function template is not a function. A fully specialized function template is a function.

Since all (odr-used) functions must be defined, you must have a way to generate definitions for arbitrary template instantiations. Thus the definition of the primary function template must be in the header.

header.h:

template <typename T>            //  this
const char * GetTypeName()       //  is
{                                //  not
    return "foo";                //  a
}                                //  function

template <>
const char * GetTypeName<int>();

impl.cpp:

#include "header.h"

template <>
const char * GetTypeName<int>()
{
    return "int";
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • But I plan to use only specialized versions. I must provide definition for function template even in this case? – Shadows In Rain Apr 24 '13 at 22:42
  • @ShadowsInRain No. The compiler only needs a definition for the instantiations that it uses. If you only use specialized versions, then those are the only definitions you need. – James Kanze Apr 24 '13 at 22:48
  • @JamesKanze And so it is. I am using specialized versions only, they are declared in headers and defined in sources. – Shadows In Rain Apr 24 '13 at 23:03
  • I just tried something similar to this, with a call in `main` to `GetTypeName` and it compiled, linked, an ran. But if I move the *definition* of the template to the source file, I get the link error "undefined reference to `GetTypeName`. What would the correct way to define the template in the source file be? – sancho.s ReinstateMonicaCellio Apr 08 '21 at 02:11