Forcing instantiation of all of a template classes member functions - c++

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.

Related

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.

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's static variable initialization, c++

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.

Is dynamic instantiation of a class template considered as explict or implicit?

If I have a class template and I use a smart pointer to a dynamically allocated instance of a specialized instance, does that cause the entire class template to be defined by the complier or will it also wait for a member function to be called from the pointer before it is instantiated?
template <class T>
class Test {
public:
void nothing();
void operation();
static const int value;
};
template <class T>
const int Test<T>::value = 100;
template <class T>
void Test<T>::nothing() {
/* invalid code */
int n = 2.5f;
}
template <class T>
void Test<T>::operation() {
double x = 2.5 * value;
}
int main() {
std::unique_ptr<Test<int>> ptr = new Test<int>(); // mark1
ptr->operation(); // mark2
return 0;
}
Does the entire class template get instantiated at mark1?
If not does that mean this code will compile correctly and the member function Test::nothing() not be instantiated?
Does the entire class template get instantiated at mark1?
Yes. The class template is implicitly instantiated — only the class template, not all its members.
If not does that mean this code will compile correctly and the member function Test::nothing() not be instantiated?
The not doesn't imply that, rather if nothing() is not used, it is not instantited.
The full answer to this probably depends highly on what compiler you are using.
At //mark1, the compiler will notice that at least portions of the Test<int> class need to instantiated. Whether or not it does it right then, or in a later phase, is up to the compiler designer.
At //mark2, Test<int>.operation() is obviously needed, it is either marked for later instantiation or created on the spot, again depending on what the compiler designers decided.
Since Test<int>.nothing() is never referenced, the compiler has the freedom to instantiate it or not. Some older compilers blindly instantiated the entire class, but I suspect the majority of modern compilers will only instantiate what they can prove to be necessary (or at least that they can't prove is not necessary). Again, though, where that happens within the compiler depends on the way the compiler designers built the compiler.
So as it turns out for the compiler I'm using (MS Visual C++), my supposition was correct that, for the code as presented in the question, the class template member instantiation would not take place at //mark1 but rather at //mark2 and Test<int>.nothing() would not be created by the compiler.
However, it seems I left out a critical part of the issue that I was experiencing. My actual class was a part of a virtual hierarchy, and according to the MSDN help library all virtual members are instantiated at object creation. So in the example above, if both member functions, i.e. operation() and nothing(), are virtual then at //mark2 the compiler would try to generate code for both functions and the validation of nothing() would fail.
http://msdn.microsoft.com/en-us/library/7y5ca42y.aspx
http://wi-fizzle.com/howtos/vc-stl/templates.htm#t9

Does order matter in specialization of a function in class template

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.