Reputation: 1884
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
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
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