I heard C++ templates wont generate errors until they are used. Is it true ? Can someone explain me how they work ?
Templates follow two phase compilation model.
struct X{
private:
void f(){}
};
template<class T> void f(T t){
int; // gives error in phase 1 (even if f(x) call is commented in main)
t.f(); // gives error only when instantiated with T = X, as x.f() is private, in phase 2
}
int main(){
X x;
f(x);
}
They generate compiler errors when they are compiled. They are compiled separately for each actual parameter passed as the template argument(s) (this is unlike Java Generics), e.g., if I have:
template <typename T> class foo { ... }
and
int main() {
foo<char> c;
foo<int> i ;
}
the template foo gets compiled twice, once for chars, once for ints.
If you never (directly or indirectly) instantiated or used template foo, it wouldn't be compiled and you'd not see any compiler errors.
Once compiled, they're just "normal" C++ code, and like any code, can generate runtime errors.
From here,
From the point of view of the
compiler, templates are not normal
functions or classes. They are
compiled on demand, meaning that the
code of a template function is not
compiled until an instantiation with
specific template arguments is
required. At that moment, when an
instantiation is required, the
compiler generates a function
specifically for those arguments from
the template.
Hope it helps..
Conceptually, at the highest level
template <Type value, class Y, ...>
...fn-or-class...
may be usefully compared to
#define FN_OR_CLASS(VALUE, TYPE_Y, ...) \
...fn-or-class...
Both basically wait until called/instantiated then substitute the specified types and values to produce tailored code with full compile-time optimisation for those values. But, templates differ from #defines in that they're proper compile-stage constructs that can be enclosed in namespaces, must satisfy the lexer, and not all of a class template is generated when the first instantiation is seen - rather, functions are generated on an as-needed basis.
When the compiler first encounters a template, it does a rough check that the template's content could make sense for some hypothetical instantiation. Later, when it encounters a specific instantiation, then for class templates only the functions that are used are further checked to make sure they can be compiled with the specific parameters in use. This does mean that a class template can appear - for some limited usage - to support instantiation with specific parameters, but if you start using some other functions in the template API then suddenly you can find that it can't be compiled with that presumed-suitable parameter... can force you to redesign your usage rather late in the day. That is one of the reasons that C++0x had planned to introduce Concepts: they elegantly allow templates to check that parameters meet all the template's expectations - if they allow any instantiation, then the user can assume that the full API of the template can be used.
template <class T>
struct X
{
void f() { }
void g() { T::whatever(); } // only error if g() called w/o T::whatever
};
int main()
{
X<int> x;
x.f();
// x.g(); // would cause an error as int::whatever() doesn't exist...
}
The SFINAE (substitution failure is not an error) technique can then allow the compiler to select between multiple nearly-matching functions based on the actual instantiating template parameters. This can be used to implement basic compile-time introspection, such as "does this class have a member function fn(int)?".
Related
I have a fair understanding of how type-template parameters get compiled. But do non-type templates get compiled the same way?
For instance, with a type-template like this:
template<typename T>
class TemplatedClass {
..do something with T..
};
TemplatedClass<int> IntClass;
TemplatedClass<char> CharClass;
The above would get compiled to separate class definitions for int and char:
class TemplatedClass<int> {
..do something with int..
};
class TemplatedClass<char> {
..do something with char..
};
When templating non-type parameters, does the compiler do it the same way? For instance:
template<int N>
class NumericClass {
int array[N];
..do something else with N..
};
NumericClass<3> Class3;
NumericClass<5> Class5;
Would this generate separate class definitions for each of the numeric values as below?
class NumericClass3 {
int array[3];
..do something else with 3..
};
class NumericClass5 {
int array[5];
..do something else with 5..
};
If so, couldn't that lead to a ton of bloated compiled code if there are a significantly large number of numeric possibilities for the template parameter? I could have a static array class defined with a numeric template in my core API. Then every time I declared an instance with a unique length value, it would have to compile a new class definition for it. This could lead a ridiculously large number of compiled definitions, assuming my code is open-ended.
As far as I know, this is still encouraged practice. Does the compiler have some other way of dealing with non-type templates then? Or are the overheads from having it compiled this way not all that significant?
Each template instantiation is conceptually a different entity. The compiler can create different code for each instantiation. It doesn't matter whether the template arguments are type or non-type arguments. The compiler may be able to share code between different instantiations and give different symbols to the same object code but there is certainly no mandate to do so (there is still some storage needed for the symbols at least until the code is linked).
As a result, it can be important to structure implementations in a way minimizing the code which is specific to template arguments. For example, it may be reasonable to factor code common to multiple instantiations into a base class (assuming the functionality has to be a member functions). For the remaining code it is reasonable to make it rather small so that it can be inlined and not create any overhead if it is smaller than code needed to call functions and return from them.
I am using g++ compiler. I wrote the following code which has a template class definition. The class has a struct data-type called node which has elements a and b of the generic type. The class has one function called print which prints p.h where p is a variable of type node of the class object. The compiler does not show any errors although 'h' is not an element of struct node. Why is that?
#include<iostream>
#include<cstdlib>
using namespace std;
template <typename e>
class mc
{
typedef struct node
{
e a,b;
}node;
node p;
public:
void print();
};
template <typename e>
void mc<e>::print()
{
std::cout<<p.h;
}
int main()
{
mc<int> m;
//m.print();
return(0);
}
The compiler shows an error only when m.print() is uncommented in main. Why is that?
If you donot use the object (instance) of a template, compiler only check the logic of the template. The template will not be instantiated. But if you try to use a instance of a template, that template will be instantiated (expanded) then you will see the error that h is not a member of p.
That is to say that , if you comment out //m.print(), the template will be instantiated.
In order to make writing template classes a bit easier, non-invoked template methods are not instantiated.
A few things are checked -- the signature of the method, and it does lookup of any methods or functions that involve only data non-dependent on the template parameters of the class and the like.
In this case, p is technically dependent on the template parameters of the class, so the check that p.h is valid is done at instantiation. Now, you could prove that there is no e such that p.h is valid, but the compiler doesn't have to, so it doesn't bother.
The program may still be ill-formed: there are clauses in the standard where programs can be ill-formed (no diagnostic required) if there are no valid specializations of a template, but I do not know if that applies to a method of a template or not.
Once you invoke print, the method is instantiated, and the error is noticed.
An example of where this is used in the std library is vector -- a number of its methods, including <, blinding invoke < on its data. vector does not require that its data support <, but it does require it if anyone tries to call <.
Modern C++ techniques would involve disabling vector::operator< in that case (the standard talks about "does not participate in overload resolution"), and in C++1z this becomes far easier via requires clauses (if that proposal ever gets standardized).
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
I just read the wiki article about CRTP, and I'm a little confused about template instantiation.
According to the wiki,
member function bodies (definitions) are not instantiated until long
after their declarations.
I don't quite understand what it means.
Suppose I got a class template:
template <typename T>
class A
{
public:
void foo(T t)
{
//...
};
};
When I instantiate the class template A, does it instantiate the member function foo()?
For example:
//in .cpp file
int main()
{
A<int> a; //question 1
//class template is instantiated here, isn't it?
//What about foo(), is it instantiated too?
a.foo(10); //question 2
//according to the quotation, foo() will not be instantiated until it is used.
//if so, foo() is instantiated right here, not in question 1, right?
}
You seem to be confusing one thing:
Instantiation happens during compilation, not during runtime. Hence you can't say "on which line" a class template or a function template was instantiated.
That said, you're right about the fact that member function templates aren't instantiated together with class templates.
You could observe it in such a case: You have the following files
template.h (defines class A and function A::foo)
a.cpp (uses A)
b.cpp (uses A and A::foo)
Then during compilation of a.cpp, only A would be instantiated. However, during compilation of b.cpp, both would be instantiated.
Because of this, in case A::foo contained some semantically invalid code for a given set of template parameters, you would get compile errors in b.cpp, but not a.cpp.
I hope that clears things up!
With class templates, the rule of thumb is that only those members are instantiated which are actually used.
If you want complete instantiation, C++ offers explicit instantiation (however, usually you don't; the fact that not every bit is fully instantiated means that your template class is even more generic as it lowers the requirements on T, note that syntax checking and lookup of non-dependent types (stuff that is not dependent on T) still happens).
You will find a more complete answer here: Template instantiation details of GCC and MS compilers
Could anyone provide a comparison or specific details of how is template instantiation
handled at compile and/or link time in GCC and MS compilers? Is this process different
in the context of static libraries, shared libraries and executables?
I found this doc about how GCC handles it but I'm not sure if the information
is still referring to the current state of things. Should I use the flags
they suggest there when compiling my libraries e.g. -fno-implicit-templates?
What I know (might not necessarily be correct) is that:
templates will be instantiated when actually used
templates will be instantiated as a result of explicit instantiations
duplicate instantiation is usually handled by folding duplicate instantiations, or by deferring instantiation until link time
Point of instantiation
templates will be instantiated when actually used
Not exactly, but roughly. The precise point of instantiation is a bit subtle, and I delegate you over to the section named Point of instantiation in Vandevoorde's/Josuttis' fine book.
However, compilers do not necessarily implement the POIs correctly: Bug c++/41995: Incorrect point of instantiation for function template
Partial instantiation
templates will be instantiated when actually used
That is partially correct. It is true for function templates, but for class templates, only the member functions that are used are instantiated. The following is well-formed code:
#include <iostream>
template <typename> struct Foo {
void let_me_stay() {
this->is->valid->code. get->off->my->lawn;
}
void fun() { std::cout << "fun()" << std::endl; }
};
int main () {
Foo<void> foo;
foo.fun();
}
let_me_stay() is checked syntactically (and the syntax there is correct), but not semantically (i.e. it is not interpreted).
Two phase lookup
However, only dependent code is interpreted later; clearly, within Foo<>, this is dependent upon the exact template-id with which Foo<> is instantiated, so we postponed error-checking of Foo<>::let_me_alone() until instantiation time.
But if we do not use something that depends on the specific instantiation, the code must be good. Therefore, the following is not well-formed:
$ cat non-dependent.cc
template <typename> struct Foo {
void I_wont_compile() { Mine->is->valid->code. get->off->my->lawn; }
};
int main () {} // note: no single instantiation
Mine is a completely unknown symbol to the compiler, unlike this, for which the compiler could determine it's instance dependency.
The key-point here is that C++ uses a model of two-phase-lookup, where it does checking for non-dependent code in the first phase, and semantic checking for dependent code is done in phase two (and instantiation time) (this is also an often misunderstood or unknown concept, many C++ programmers assume that templates are not parsed at all until instantiation, but that's only myth coming from, ..., Microsoft C++).
Full instantiation of class templates
The definition of Foo<>::let_me_stay() worked because error checking was postponed to later, as for the this pointer, which is dependent. Except when you would have made use of
explicit instantiations
cat > foo.cc
#include <iostream>
template <typename> struct Foo {
void let_me_stay() { this->is->valid->code. get->off->my->lawn; }
void fun() { std::cout << "fun()" << std::endl; }
};
template struct Foo<void>;
int main () {
Foo<void> foo;
foo.fun();
}
g++ foo.cc
error: error: ‘struct Foo<void>’ has no member named ‘is’
Template definitions in different units of translation
When you explicitly instantiate, you instantiate explicitly. And make all symbols visible to the linker, which also means that the template definition may reside in different units of translation:
$ cat A.cc
template <typename> struct Foo {
void fun(); // Note: no definition
};
int main () {
Foo<void>().fun();
}
$ cat B.cc
#include <iostream>
template <typename> struct Foo {
void fun();
};
template <typename T>
void Foo<T>::fun() {
std::cout << "fun!" << std::endl;
} // Note: definition with extern linkage
template struct Foo<void>; // explicit instantiation upon void
$ g++ A.cc B.cc
$ ./a.out
fun!
However, you must explicitly instantiate for all template arguments to be used, otherwise
$ cat A.cc
template <typename> struct Foo {
void fun(); // Note: no definition
};
int main () {
Foo<float>().fun();
}
$ g++ A.cc B.cc
undefined reference to `Foo<float>::fun()'
Small note about two-phase lookup: Whether a compiler actually implements two-phase lookup is not dictated by the standard. To be conformant, however, it should work as if it did (just like addition or multiplication do not necessarily have to be performed using addition or multiplication CPU instructions.
Edit: It turns out that what I wrote below is contrary to the C++ standard. It is true for Visual C++, but false for compilers that use "two-phase name lookup".
As far as I know, what you say is correct. Templates will be instantiated when actually used (including when declared as a member of another type, but not when mentioned in a function declaration (that does not have a body)) or as a result of explicit instantiations.
A problem with templates is that if you use the same template (e.g. vector) in several different compilation units (.cpp files), the compiler repeats the work of instantiating the template in each .cpp file, thus slowing down compilation. IIRC, GCC has some (non-standard?) mechanism that can be used to avoid this (but I don't use GCC). But Visual C++ always repeats this work, unless you use explicit template instantiation in a precompiled header (but even this will slow down your compile, since a larger PCH file takes longer to load.) Afterward, the linker then eliminates the duplicates. Note: a comment below linked to a page which tells us that not all compilers operate this way. Some compilers defer function instantiation until link time, which should be more efficient.
A template is not fully instantiated when it is first used. In particular, functions in the template are not instantiated until they are actually called. You can easily verify this by adding a nonsense function to a template you are actively using:
void Test() { fdsh "s.w" = 6; wtf? }
You won't get an error unless you instantiate the template explicitly, or try to call the function.
I expect static libraries (and object files) will store the object code of all templates that were instantiated. But if your program has a certain static library as a dependency, you can't actually call the template functions that were already instantiated therein, at least not in VC++, which always requires the source code (with function bodies) of a template class in order to call functions in it.
I don't think it's possible to call a template function in a shared library (when you don't have the source code of the template function you want to call).