I am experimenting with specialized destructors. This code is perfectly valid and compiles just fine:
#include <iostream>
using namespace std;
template <typename T>
class Cat
{
public:
~Cat();
};
template <typename T>
Cat<T>::~Cat()
{
std::cout << "T" << std::endl;
}
template <>
Cat<int>::~Cat()
{
std::cout << "int" << std::endl;
}
int main()
{
Cat<int> c1;
Cat<float> c2;
return 0;
}
However if I put the class and the destructors in a separate file "Cat.h" and do #include "Cat.h" in Main.cpp, I'm getting a linker error: LNK2005 "public: __thiscall Cat<int>::~Cat<int>(void)" (??1?$Cat#H##QAE#XZ) already defined in Cat.obj. Why?
It sounds like you have the following:
template <>
Cat<int>::~Cat()
{
std::cout << "int" << std::endl;
}
in a header file that is included in two translation units. An explicit specialization of a function template is a non-inline function (C++14 [temp.expl.spec]/12); so this is an ODR violation.
It's the same error you'd get if you implemented a non-template member function (or a free function) in the same place: both translation units end up with a copy of the function, which is not allowed even if the two copies are identical.
To fix this, put the keyword inline before template<>.
There was some discussion in comments about the legality of providing an explicit specialization for a member function of a class template. I believe this is correct, with restrictions according to C++14 [temp.expl.spec]/6:
If a template, a member template or 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; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the
program is ill-formed, no diagnostic required.
Also, section 7:
The placement of explicit specialization declarations for function templates, class templates, variable templates, member functions of class templates, static data members of class templates, member classes of class templates, member enumerations of class templates, member class templates of class templates, member function templates of class templates, static data member templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, static data member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, variable templates, member class templates of non-template classes, static data member templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its
location; or to make it compile will be such a trial as to kindle its self-immolation.
In your program it is in the perfect location: immediately after the class definition. The risky sitautions occur when the class might have been instantiated before a declaration at least of the specialization was encountered.
Chances are your Cat.cpp and main.cpp translation units both include the same Cat.h header file. Put your entire template class in a header file, remove the Cat.cpp translation unit and compile without it.
Live example
More details in this SO post:
Why can templates only be implemented in the header file?.
Related
Is it O.K. to define virtual function of class template outside its body? Virtual function can not be inlined, but to avoid multiple definitions in compilation units they shall be marked inline (assuming that template headers will be included in multiple source files). On the other hand compiler is free to ignore inline, so this seems valid. By an example, is the code below correct:
template <typename T>
class C
{
public:
virtual void f(T val);
};
template <typename T>
inline
void C<T>::f(T val)
{
//definition
}
?
BTW gcc (3.4.2) allows to omit inline before definition of function f(T val) but not before analogous function of regular class. Is it only gcc's behaviour?
Yes, it's OK even without inline. It works the same for ordinary member functions and static variables:
// everything in the header:
template <class T>
class A
{
static int i;
};
template <class T>
int A<T>::i=0;
Standard quote: (3.2/5)
There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with
external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member
of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for
which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition
appears in a different translation unit, and provided the definitions satisfy the following requirements ...
The requirements basically say the two definitions have to be identical.
It doesn't work in case of regular classes. There has to be at most one definition in the whole program.
You can define template methods outside the class definition, in the same header, without using inline and without receiving multiple definition errors.
That's because a template function doesn't generate a definition itself, if it's not fully specialized. To prove my point, the following:
void C<int>::f(int)
{
}
will result in a linker error, as the function has a definition in this case. (provided you include this in multiple translation units. If you mark it inline:
inline void C<int>::f(int)
{
}
the error no longer occurs.
You can define the functions there, as long as any code which needs to instantiate the function in question has visibility of that code at compile time (not link time).
It's quite common to separate a template into 2 files, one being a traditional header, and the second being the implementation, as with non-templated functions and their implementation. The only difference is that you need to #include the template implementation file as well as the header when you want to use it.
consider the following code:
//header.h
template<class T>
class A
{
static int x;
};
template<class T>
int A<T>::x = 0;
//source1.cpp
#include "header.h"
void f(){} // dummy function
//main.cpp
#include "header.h"
int main(){}
In this case code compiles perfectly without errors, but if I remove the template qualifier from class
class A
{
static int x;
};
int A::x = 0;
In this case compiler erred with multiple definition of x. Can anybody explain this behavior?
And when the template class's static variable is initialized / instantiated??
Compiler will remove duplicate template instantiations on its own. If you turn your template class into regular one, then its your duty to make sure only one definition of static variable exists (otherwise linker error will appear). Also remember that static data members are not shared between instatiations of templates for different types. With c++11 you can control instatiations on your own using extern templates: using extern template (C++11).
As for the point of instatiation for static members:
14.6.4.1 Point of instantiation [temp.point]
1 For a function template specialization, a member function template specialization, or a specialization for a
member function or static data member of a class template, if the specialization is implicitly instantiated
because it is referenced from within another template specialization and the context from which it is referenced
depends on a template parameter, the point of instantiation of the specialization is the point of
instantiation of the enclosing specialization. Otherwise, the point of instantiation for such a specialization
immediately follows the namespace scope declaration or definition that refers to the specialization.
so point of instatiation should be ie. right after main() if you use your type for the first time inside main().
Templates as the name suggest are the the fragments of code that will be used several times for different parameters. For templates the compiler is to ensure if their methods and static fiels definition are linked only ones. So if you create a static field with its default value the compiler is obliged to provide single memory cell (for the same template parameter set) even though the template class header is included several times. Unfortunetly non-template classes you need to be managed by yourself.
As for the second question, I believe the standard does not state when the static fields need to be initialized, each compiler can implement then it in its own manner.
It is necessary to instantiate/initialize static members in cpp files not in headers. Static members are property of class not property of objects, so if you include header file in more cpp files, it looks like you are initializing it more times.
Answer to this question is more complex. Template is not one class. It is instantiating on demand. It means that every different use of template is one standalone "template instance". For example if you use A<int> and A<float> than you will have 2 different classes therefore you would need to initialize A<int>::x and A<float>::x.
For more info see this answer: https://stackoverflow.com/a/607335/1280316
A class (be it a template or not) can (and should) be declared in any compilation unit that referes to it.
A static field initialization does defines a variable, and as such it should exist only in one compilation unit -> that's the reason why you get an error when class A is not a template.
But when you declare a template, nothing is really created untill you instantiate it. As you never instantiate the template, the static field is never defined and you get no error.
If you had two different instantiations in source1.cpp (say A<B>) and main.cpp (say A<C>) all will still be fine : you would get A<B>::x in source1 and A<C>::x in main => two different variables since A<B> and A<C> are different classes.
The case where you instantiate same class in different compilation units is trickier. It should generate an error, but if it did, you could hardly declare special fields in templates. So it is processed as a special case by the compiler as it is explained in this other answer to generate no errors.
My network code uses template specialization to serialize types that can not simply be copied. I defined a general template
template<typename T> struct TypeHandler
that handles all types that can be transported by a simple memcpy and then I define specializations for all other types. The problem now is that I have a file with multiple such specializations and if I compile the code with Visual Studio everything works fine. But with gcc all template specializations in that file get used with the exception of
template<> struct TypeHandler<uint32_t>
which variable length encodes the integer to save space.
Namespaces are the same for all TypeHandler versions and they are even in the same file. But for some reason gcc decides to use the generalized version and I don't really know why.
EDIT:
It seems that gcc uses the instantiation of TypeHandler from an other project that this one links against but doesnt have a specialization for uint32_t even so it transmits uint32_t fields. GCC doesnt give me any error though. How can i tell gcc to use the specialization like Visual Studio does ?
EDIT2:
managed to generate an SSCCE http://netload.in/dateiz3R4eTVqi3/src.tar.gz.htm
the bug here is the other way around but well.
EDIT3:
fixed filesize : http://netload.in/dateixP6iOvc6bD/src.zip.htm
Minimized to:
test1.cpp:
#include <iostream>
#include <stdint.h>
template<typename T>
struct TypeHandler
{
void Print() { std::cout << "base" << std::endl; }
};
void test1()
{
std::cout << "p1" << std::endl;
TypeHandler<uint32_t>().Print();
}
test2.cpp:
#include <iostream>
#include <stdint.h>
template<typename T>
struct TypeHandler
{
void Print() { std::cout << "base" << std::endl; }
};
template<>
struct TypeHandler<uint32_t>
{
void Print() { std::cout << "int" << std::endl; }
};
void test2()
{
std::cout << "p2" << std::endl;
TypeHandler<uint32_t>().Print();
}
main.cpp:
void test1();
void test2();
int main(){
test1();
test2();
}
On Windows/MinGW 4.8.2, compiling with g++ test1.cpp test2.cpp main.cpp -o test and running produces
p1
base
p2
base
while using g++ test2.cpp test1.cpp main.cpp -o test produces
p1
int
p2
int
This is a straightforward standard violation causing undefined behavior. You can't explicitly specialize the same template in one translation unit but not the other. The explicit specialization is not visible in test1.cpp, causing the compiler to generate an implicit instantiation from the base template. So you get two TypeHandler<uint32_t> specializations, and in this instance it appears that the linker decided to pick the one from the first object file it saw. From §14.7.3 [temp.expl.spec]/p6 of the standard (emphasis mine):
If a template, a member template or 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; no diagnostic is required. If the program
does not provide a definition for an explicit specialization and
either the specialization is used in a way that would cause an
implicit instantiation to take place or the member is a virtual member
function, the program is ill-formed, no diagnostic required. An
implicit instantiation is never generated for an explicit
specialization that is declared but not defined.
Also, obligatory quote of the next paragraph (emphasis mine):
The placement of explicit specialization declarations for function
templates, class templates, member functions of class templates,
static data members of class templates, member classes of class
templates, member enumerations of class templates, member class
templates of class templates, member function templates of class
templates, member functions of member templates of class templates,
member functions of member templates of non-template classes, member
function templates of member classes of class templates, etc., and the
placement of partial specialization declarations of class templates,
member class templates of non-template classes, member class templates
of class templates, etc., can affect whether a program is well-formed
according to the relative positioning of the explicit specialization
declarations and their points of instantiation in the translation unit
as specified above and below. When writing a specialization, be
careful about its location; or to make it compile will be such a trial
as to kindle its self-immolation.
Is it O.K. to define virtual function of class template outside its body? Virtual function can not be inlined, but to avoid multiple definitions in compilation units they shall be marked inline (assuming that template headers will be included in multiple source files). On the other hand compiler is free to ignore inline, so this seems valid. By an example, is the code below correct:
template <typename T>
class C
{
public:
virtual void f(T val);
};
template <typename T>
inline
void C<T>::f(T val)
{
//definition
}
?
BTW gcc (3.4.2) allows to omit inline before definition of function f(T val) but not before analogous function of regular class. Is it only gcc's behaviour?
Yes, it's OK even without inline. It works the same for ordinary member functions and static variables:
// everything in the header:
template <class T>
class A
{
static int i;
};
template <class T>
int A<T>::i=0;
Standard quote: (3.2/5)
There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with
external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member
of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for
which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition
appears in a different translation unit, and provided the definitions satisfy the following requirements ...
The requirements basically say the two definitions have to be identical.
It doesn't work in case of regular classes. There has to be at most one definition in the whole program.
You can define template methods outside the class definition, in the same header, without using inline and without receiving multiple definition errors.
That's because a template function doesn't generate a definition itself, if it's not fully specialized. To prove my point, the following:
void C<int>::f(int)
{
}
will result in a linker error, as the function has a definition in this case. (provided you include this in multiple translation units. If you mark it inline:
inline void C<int>::f(int)
{
}
the error no longer occurs.
You can define the functions there, as long as any code which needs to instantiate the function in question has visibility of that code at compile time (not link time).
It's quite common to separate a template into 2 files, one being a traditional header, and the second being the implementation, as with non-templated functions and their implementation. The only difference is that you need to #include the template implementation file as well as the header when you want to use it.
Consider something like...
template<typename T>
class Vector {
...
bool operator==( const Vector<float> &rhs ) {
// compare and return
}
bool operator==( const Vector<T> &rhs ) {
// compare and return
}
...
};
Notice how the specialization is above the non specialized version. If I were to put the specialized version below the non-specialized version, would a Vector<float> == comparison still work as intended? For some reason I think I remember reading that if you put the specialization below in this scenario then when the compiler looks through the header, it will see the default first, see that it works, and use that.
Your example code is not specializing, but overloading. The order does matter (not in your code though), because functions need to be declared before being known in C++. So if one overload calls another, or if another function in between calls the overload set, calls may end up somewhere not desired. Your example code is valid and common.
For some reason I think I remember reading that if you put the specialization below in this scenario then when the compiler looks through the header, it will see the default first, see that it works, and use that.
You are thinking of the following rule
If a template, a member template or the 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; no diagnostic is required.
I can't help but to quote the hilarious sayings of the Standard here about specializations
The placement of explicit specialization declarations for function templates, class templates, member functions of class templates, static data members of class templates, member classes of class templates, member class templates of class templates, member function templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, member class templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
As written, I believe you have an error. You aren't specializing operator==, you're overloading it. You aren't allowed to overload on a template parameter like that.
If your method were a free function, then you could specialize it. For instance
template <typename T>
void Foo(Vector<T> x) {
std::cout << "x" << std::endl;
}
template <>
void Foo(Vector<float> y) {
std::cout << "y" << std::endl;
}
...
Vector<int> intVec;
Vector<float> floatVec;
Foo(intVec); //prints x
Foo(floatVec); //prints y
In this case, if you call Foo with Vector<float>, you'll call the specialized version.
Order matters to some degree. First of all, the compiler will always favor a specialization over an unspecialized form when one is available. After that, the compiler will try to instantiate each function in order. If it can compile it successfully, that specialization will be used. If it can't, it will move on to the next one. This principle s called Substitution Failure is not an Error (SFINAE). http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error has a much more detailed description.