Does order matter in specialization of a function in class template - c++

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.

Related

Forcing instantiation of all of a template classes member functions

During initial development of a template class, before I've written full test cases, I am finding that I would like the ability to force the compiler to generate the code for every member (including non-static ones) of a template class for a specific set of template parameters, just to make sure all the code at least compiles.
Specifically, I'm using GCC 9 (I don't really need this ability for other compilers, since it's just something I want to temporarily make happen during development); and its c++14, c++17, c++2a and c++20 standards.
For example, I might write the following code:
template <typename D> struct test_me {
D value;
void mistake1 () { value[0] = 0; }
void mistake2 () { mistake1(value); }
// and a bajillion other member functions...
};
And, given that I know in advance the finite set of possible template parameters (let's say int and float here), I just want to make sure they at least compile while I'm working.
Now I can do this, which obviously falls short:
int main () {
test_me<int> i;
test_me<float> f;
}
Since mistake1 and mistake2 aren't generated, the code compiles fine despite the indexed access attempt to a non-array type, and the incorrect function call.
So what I've been doing during development is just writing code that calls all the member functions:
template <typename D> static void testCalls () {
test_me<D> t;
t.mistake1();
t.mistake2();
// and so on... so many mistakes...
}
int main () {
testCalls<int>();
testCalls<float>();
}
But this gets to be a pain, especially when the member functions start to have complex side effects or preconditions, or require nontrivial parameters, or have non-public members and not-yet-developed friends. So, I'd like a way to test compilation without having to explicitly call everything (and, ideally, I'd like to be able to test compilation without modifying any "test" code at all as I add new members).
So my question is: With at least GCC 9, is there a way to force (potentially temporarily) the compiler to generate code for a template class's entire set of members, given template parameters?
Just explicitly instantiate the class:
template struct test_me<int>;
template struct test_me<float>;
Demo
What you are trying to do is not allowed by the language, at least with implicit instantiations of your test class. When you implicitly instantiate test_me with some type, the definitions of the member functions are not allowed to be implicitly instantiated, as per temp.inst#11:
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class or static data member of a templated class, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.
So if you want to implicitly instantiate all the mistake member functions, you have no choice but to require their instantiation somehow. As in your example with testCalls, you can make calls to those member functions, or you can ODR-use them some other way, such as taking their addresses.

Function definition in a template class

Usually, one declares a member function in a header file and uses a source file to implement it. My understanding of the reason is that the function implementation will reside in only one translation unit and will be just linked to other units (no duplicate code), and it also allows separation of the interface and implementation, and removes the need to forward declare functions that depend on each other.
However, member functions in a template depend on the template arguments, which couldn't be known if the implementation was placed in a source file. However, it is still possible to define such functions outside the class, but the major argument for it doesn't apply anymore.
So, which is better?
template <class T>
class A
{
T m()
{
return T();
}
};
or
template <class T>
class A
{
T m();
};
template <class T>
T A::m()
{
return T();
}
These two pieces of code would be equivalent if it was inline T A::m(), but is there any difference without it? What if the function is virtual? Is it just a matter of coding style, or does it have different semantics? If the function is large enough, will it prevent duplicate code, or is the compiler smart enough not to inline it if it won't bring any benefits?
These two pieces of code would be equivalent if it was inline T A::m(), but is there any difference without it?
Not for templates, the member functions are implicitly inline, for both inside and outside the class definitions.
What if the function is virtual?
Makes no difference.
Is it just a matter of coding style, or does it have different semantics?
Mostly stylistic. However, it affects how name lookup works. So if we were to modify the class definition a bit
template <class T>
class A
{
using foo = T;
foo m();
};
We would not be able to define the member outside as
template <class T>
foo A<T>::m()
{
return T();
}
Since the lookup for foo doesn't happen inside the class definition until after the qualification A<T>::. We'd need to either fully qualify foo itself, like so typename A<T>::foo. Or perhaps use a trailing return type.
If the function is large enough, will it prevent duplicate code, or is the compiler smart enough not to inline it if it won't bring any benefits?
Neither style should have either an adverse of positive effect on it. Both are subject to quality of implementation issues. But of course, different implementations may have different qualities.

"Destructor already defined" with a specialized destructor

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?.

How do template member functions work in c++?

I'm wondering how template member functions work. In particular, when there is an instantiation of the template member function, is the whole class redefined? My confusion comes from the fact that (if I'm right) template classes are not classes in the proper sense. i.e., when instantiated, the compiler creates the definition for a completely new class. The same for template functions. However, classes with a template function seem to be actual classes, so I'm not sure how they could possibly work. Thus, I'm wondering, after instantiating a template member function, what happens with the class definition? Moreover, if I pass a class with a template member function to a template class, can I use the template member function? Could that cause a problem? I tried it once but got an error saying that several functions where defined more that once, although I'm not sure if that was the reason or if there could be an other reason for my error. Is there any further caveat when using static template member functions?
The class definition remains as it is; all the template function does is generate a family of member functions for that class. As an example:
class A {
public:
template<typename T> foo (T &t);
}
Is not conceptually different from you writing:
class A {
public:
foo (bool &t);
foo (int &t);
foo (double &t);
}
...just more convenient. And in the last example, you wouldn't expect a new class to be created for each function would you?
Perhaps the confusion comes from the notion that functions are somehow part of the memory layout of a class; that each function is itself contained in the class, and will be instantiated somewhere in memory whenever an object of the class is created. This notion is incorrect. Functions (templated, global, member, lambda, or otherwise) are never created on the fly or copied around in memory; they are a static and unchanging part of the executable image. The memory layout of the class is not changed by the presence of an extra set of functions, even if those happen to be generated by a template member.
The template class definition is instantiated when you instantiate a class. Each member function of it is instantiated when used. This actually allows you to have member functions that would not work if called when the class is instantiated with some types and not others. However, you must ensure that the signature of the function is either syntactically viable or fails with SFINAE. It will be looked up during the first phase of parsing. The body, if the function isn't itself a template, will be checked for name lookup...so dependent names have to be labeled as such via typename.

Template class in C++

We have following class definition
template<typename T>
class Klass {...}
and we also have below two instantiations
Klass<int> i;
Klass<double> d;
how many copies of Klass' methods are generated by the C++ compiler?
Can somebody explain it? Thanks!
Klass isn't a type, so it doesn't make sense to talk of Klass's methods. Kalss<int> is a type with it's own methods, and so is Klass<double>. In your example there would be one set of methods for each type.
Edit in real life, it isn't as simple as that. The question of the actual existence of the methods also depends on other factors, see #KerrekSB's answer to this question.
Each template instance is an entirely separate, distinct and independent type of its own. However, the code for class template member functions is only generated if the member function is actually used for a given template instantiation (unless you instantiate the template explicitly for some set of parameters). Among other things, this means that if some class template member function's body doesn't actually make sense for a given template parameter, then you can still use the overall template as long as you don't invoke that member function, since the code for the member function will never get compiled.
Also bear in mind that templates can be specialized:
template <typename T> struct Foo {
int bar;
void chi();
};
template <> struct Foo<int> {
double bar(bool, char) const;
typedef std::vector<bool> chi;
bool y;
};
As you can see, there's a lot you cannot just tell from a template itself until you see which actual instantiations you'll be talking about.