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.
Related
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.
Is there a good rule when to use a class template instead of using member templates?
As I understand it, your are forced to use a class template if your class contains member variable templates but otherwise you are free of choice since this:
template<typename T>
class Foo
{
public:
void someMethod(T x);
};
behaves like this:
class Foo
{
public:
template<typename T>
void someMethod(T x);
};
Is my claim wrong? Or is there any rule of thumb when to use what?
The two are not at all the same. With the first:
Foo<int> f;
f.someMethod('a');
the called function is someMethod(int).
With the second:
Foo f;
f.someMethod('a');
the called function is someMethod(char).
You can choose to make your class a template, rather than having member function templates, for several reasons. Say you have a template parameter T.
Like you said, if you have a member variable of type T, your class needs to be a template.
If you have a function returning T and not accepting T, and you don't want to manually specify the type in each invocation, your class needs to be a template.
If you need a virtual function that depends on T, your class needs to be a template.
If you need a different class layout (i.e. member variables) per instantiation of T, your class needs to be a template.
If you need to make sure that your functions all operate on a single type rather than generate different versions of them arbitrarily, your class needs to be a template.
The best rule of thumb would be to use the simplest thing that makes sense. In general, member function templates tend to be more rareāand virtually non-existent for the use case you're talking about. Maybe that's no coincidence.
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.
Where do I have to specify default template parameters of classes member functions (assuming that the declaration is (of course) in the "class body", and the function definition is outside the class body) for each case in C++2011 :
"normal" functions
static functions
friend functions
In the definition, in the declaration or both ?
Well,
From my experiences creating template classes and methods, you specify a template function as such:
template<typename T>
T MyFunc(T &aArg1, T &aArg2)
{
//...Definition Goes Here
}
The typename T is the template argument type for the template function and you need to pass that data type consistently to each argument labeled as "T". This means that aArg2 has to be whatever data type aArg1 is. Now, when you call this function, you call it like so:
MyFunc</*datatype*/int>(iArg1, iArg2); the two arguments have to be data type "int" or you'll get a warning or an error.
Now, this also applies to class methods (I think that is what you meant by "classes member functions") which are the functions supplied by the class (i.e. MyClass::MyFunc()) so when you declare a class method that is a template method, you do it in the same manner. Here is an example class:
class MyClass
{
MyClass();
~MyClass();
template<typename T>
static T MyStaticFunc(T aArg) { return aArg; }
template<typename T>
T MyFunc(T aArg) { return aArg; }
}
As you can see, not to difficult. Now, static functions are the same way you just have to be sure t define then in the same module that the class is built in, otherwise, you'll get an error.
Unfortunately, I never really use "friend" methods, so I don't know how to tackle that. I would suspect you would do it in the same way as the other two. I hoped that whole essay of an answer helped.
Trying these out in Clang suggests the following:
For non-static and static functions, specifying the default in either the definition or
the declaration is acceptable - but not both and certainly not if
they contradict one another;
For friend functions, specifying a
default inside the class definition results in an error.
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.