vukung
vukung

Reputation: 1884

Multiple instantiation of specialized templates

I have an explicitly instantiated template class with specializations:

// a.hh
#pragma once

template<int N>
struct A {
  int foo();
};

// a.in
#include "a.hh"

template<>
int A<1>::foo() { return 1; } // specialization for N=1

template<>
int A<2>::foo() { return 2; } // specialization for N=2

// a1.cc
#include "a.in"

template struct A<1>; // explicit instantiation for N=1

// a2.cc
#include "a.in"

template struct A<2>; // explicit instantiation for N=2

The above files are compiled into a static library with g++ 4.9.2:

g++ -Wall -c -o a1.o a1.cc
g++ -Wall -c -o a2.o a2.cc
ar rcs libtest.a a1.o a2.o

I would expect that a1.o contains A<1>::foo(), and a2.o contains A<2>::foo(), but not the other way around, since there is only one instantiation in each of the .cc files.

It turns out, however, that both object files contain both functions. VS2015RC also gives linker warnings:

a1.obj : warning LNK4006: "public: int __thiscall A<1>::foo(void)" already defined in a2.obj; second definition ignored
a1.obj : warning LNK4006: "public: int __thiscall A<2>::foo(void)" already defined in a2.obj; second definition ignored

Why?

Also, if I comment out the specialization for N=2, with g++ it still compiles silently, even though the explicitly instantiated N=2 case has an unresolved function... (VS2015RC warns that "no suitable definition provided for explicit template instantiation request", as expected).


Clarification - according to the standard (14.7.3.6):

If a [..] member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs[.]

This passage (implicitly) states, that a use of the specialization is needed for it to be instantiated.

My problem is that A<2>::foo() is implicitly instantiated in a1.o, even though there was no use of this specification in that translation unit.

Upvotes: 2

Views: 1595

Answers (2)

marom
marom

Reputation: 5230

I would say that your code

template<>
int A<1>::foo() { return 1; } // specialization for N=1

it's an esplicit definition of the member function and as such cannot be done twice. So make sure is inside one translation unit only.

14.7.3 Explicit specialization

5 A member of an explicitly specialized class is not implicitly instantiated from the member declaration of the class template; instead, the member of the class template specialization shall itself be explicitly defined if its definition is required.

Upvotes: 1

Jarod42
Jarod42

Reputation: 217283

Your specialization are not inline. so you have one definition by translation unit including a.in.

Add inline keyword:

template<>
inline int A<1>::foo() { return 1; } // specialization for N=1

or move definition in cpp file:

// a1.cc
#include "a.hh"

template<>
int A<1>::foo() { return 1; } // specialization for N=1

template struct A<1>; // explicit instantiation for N=1

Upvotes: 3

Related Questions