C++ Tutorial
C++ functions, c++ classes, c++ data s tructures, c++ reference, c++ examples, c++ templates.
Templates are a way to allow functions and classes to use the same code for many different data types.
To declare a template you use the template keyword followed by a list of template parameters in angle brackets :
Immediately after the template declaration, you write a function or class definition the normal way. The function or class will have access to special data types and values given by the template declaration.
Use a template to create a class that can use any data type:
Example explained
- The first line template <class MyType> declares the template
- class MyType is a template parameter that makes MyType possible to represent any data type. You will learn about template parameters in the next chapter.
- MyClass<string> stringObj( "Hello", "World" ); creates a MyClass object where MyType means string
- MyClass<int> stringObj( 4, 5 ); creates a MyClass object where MyType means int
C++ Template Parameters
Template parameters are how you specify how many data types and values a template has access to.
There are two kinds of template parameters: typed parameters and non-typed parameters.
Typed Parameters
Typed parameters allow you to specify a "wildcard" data type for a class or function.
A typed parameter uses the keyword class or typename followed by a name. There is no difference between the class and typename keywords, you can use any one of them.
The syntax of a template with typed parameters looks like this:
The following example declares two different typed parameters:
- The line template <class A, class B> indicates that there are two different data types which are assigned the names A and B
- A first; creates an attribute named first of type A
- B second; creates an attribute named second of type B
- The constructor MyClass(A f, B s) has two parameters: f is of type A and s is of type B
- The line MyClass<int,string> myObj( 15, "Some Text" ); creates a MyClass object where A means int and B means string .
Non-Typed Parameters
Non-typed parameters let you pass values directly to the class or function that is using the template.
To add a non-typed parameter, write the data type of the value followed by a name. The syntax looks like this:
This example declares a class with a non-typed parameter:
- The line template <int N> indicates that the parameter N contains an integer.
- string myStrings[N]; uses the value of N to set the size of an array of strings.
- MyClass<2> myObj; creates a MyClass object and sets the value of N to 2, which results in the myStrings array having 2 strings.
Another Example
This example illustrates how to use both typed and non-typed parameters in a template class:
Templates in
COLOR PICKER
Contact Sales
If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail: [email protected]
Report Error
If you want to report an error, or if you want to make a suggestion, send us an e-mail: [email protected]
Top Tutorials
Top references, top examples, get certified.
- C++ Data Types
- C++ Input/Output
- C++ Pointers
- C++ Interview Questions
- C++ Programs
- C++ Cheatsheet
- C++ Projects
- C++ Exception Handling
- C++ Memory Management
Templates and Static variables in C++
Function templates and static variables: Each instantiation of function template has its own copy of local static variables. For example, in the following program there are two instances: void fun(int ) and void fun(double ) . So two copies of static variable i exist.
Output of the above program is:
Class templates and static variables: The rule for class templates is same as function templates Each instantiation of class template has its own copy of member static variables. For example, in the following program there are two instances Test and Test . So two copies of static variable count exist.
Similar Reads
Improve your coding skills with practice.
What kind of Experience do you want to share?
Understanding Template Class Assignment Operators in C++
When working with template classes in C++, especially those involving inheritance, you might encounter unexpected behaviors with assignment operators. One such scenario arises when using the keyword using to inherit an assignment operator that does not work as expected. In this post, we'll delve into why this might happen, particularly focusing on a templated class example.
Problem Overview
Consider you have a hierarchically structured C++ class setup where you want to inherit a base class assignment operator in a derived class. A user faced an issue where:
- They had an assignment operation not behaving as expected.
- The operation param1 = param2; resolved incorrectly, attempting to invoke a deleted copy assignment operator instead of the intended operator from the base class.
Here's a simplified version of the setup:
Why the Issue Occurs
When the statement param1 = param2; is executed, there is a misconception that param1 should receive the uint16_t type value from param2 . However, in the absence of an appropriate copy assignment operator, C++ tries to call the default copy assignment operator, which was inadvertently deleted. This arises because:
- The inherited keyword using IParameterBase<TYPE>::operator=; does not directly make the operator= from IParameterBase applicable for assigning param2 to param1 .
- The base class IParameter has a const member, rendering it non-copy-assignable, thus the compiler deletes the default assignment operator.
To resolve the issue, consider the following approaches:
Undelete the Copy Assignment Operator in IParameterBase:
- This approach allows for the correction of the undeleted operator by explicitly providing an implementation:
This effectively allows param1 = param2; to correctly invoke the function with appropriate conversion.
Use Explicit Casting:
- Another approach is to cast param2 to TYPE before performing the assignment, allowing it to match the operator= that accepts const TYPE value :
Understanding the implications of using templates with inherited classes in C++ is crucial, especially concerning assignment operators. The issue outlined demonstrates the importance of considering all operator overloads and inheritance implications. By either undeleting the default copy operator or using explicit casting, users can ensure that their template assignments operate as intended.
- Sign In / Suggest an Article
Current ISO C++ status
Upcoming ISO C++ meetings
Upcoming C++ conferences
Compiler conformance status
Meeting C++
November 14-16, Berlin, Germany
ISO C++ standards meeting
November 18-23, Wrocław, Poland
November 25, Wrocław, Poland
February 10-15, Hagenberg, Austria
using std::cpp
March 19-21, Madrid, Spain
April 1-4, Bristol, UK
June 16-21, Sofia, Bulgaria
What’s the idea behind templates?
A template is a cookie-cutter that specifies how to cut cookies that all look pretty much the same (although the cookies can be made of various kinds of dough, they’ll all have the same basic shape). In the same way, a class template is a cookie cutter for a description of how to build a family of classes that all look basically the same, and a function template describes how to build a family of similar looking functions.
Class templates are often used to build type safe containers (although this only scratches the surface for how they can be used).
What’s the syntax / semantics for a “class template”?
Consider a container class Array that acts like an array of integers:
Repeating the above over and over for Array of float , of char , of std::string , of Array-of- std::string , etc, would become tedious. Instead, you add the template<typename T> before the class definition (the T can be any identifier you want, T is just the most commonly used one, especially in examples). Then, instead of using int or float or char where referring to the data type, you use T instead. Also, instead of just referring to the class as Array, it’s Array<T> when referring to the template, or Array<int> , Array<float> , etc. when referring to a specific instantiation.
Just as with a normal class, you can optionally define your methods outside the class:
Unlike template functions , template classes (instantiations of class templates) need to be explicit about the parameters over which they are instantiating:
Note that prior to C++11, a space was required between the two > ’s in the last example. Without this space, the C++98/C++03 compiler would see a >> (right-shift) token instead of two > ’s. Aren’t you lucky that it is no longer the case in C++11?
What’s the syntax / semantics for a “function template”?
Consider this function that swaps its two integer arguments:
If we also had to swap floats, longs, Strings, Sets, and FileSystems, we’d get pretty tired of coding lines that look almost identical except for the type. Mindless repetition is an ideal job for a computer, hence a function template:
Every time we used swap() with a given pair of types, the compiler will go to the above definition and will create yet another “template function” as an instantiation of the above. Unlike template classes , template functions usually do not need to be explicit about the parameters over which they are instantiating. The compiler can usually determine them automatically. E.g.,
Note: A “template function” is the instantiation of a “function template”.
Sometimes, you do want to be explicit about the types used .
How do I explicitly select which version of a function template should get called?
When you call a function template, the compiler tries to deduce the template type. Most of the time it can do that successfully, but every once in a while you may want to help the compiler deduce the right type — either because it cannot deduce the type at all, or perhaps because it would deduce the wrong type.
For example, you might be calling a function template that doesn’t have any parameters of its template argument types, or you might want to force the compiler to do certain promotions on the arguments before selecting the correct function template. In these cases you’ll need to explicitly tell the compiler which instantiation of the function template should be called.
Here is a sample function template where the template parameter T does not appear in the function’s parameter list. In this case the compiler cannot deduce the template parameter types when the function is called.
To call this function with T being an int or a std::string , you could say:
Here is another function whose template parameters appear in the function’s list of formal parameters (that is, the compiler can deduce the template type from the actual arguments):
Now if you want to force the actual arguments to be promoted before the compiler deduces the template type, you can use the above technique. E.g., if you simply called g(42) you would get g<int>(42) , but if you wanted to pass 42 to g<long>() , you could say this: g<long>(42) . (Of course you could also promote the parameter explicitly, such as either g(long(42)) or even g(42L) , but that ruins the example.)
Similarly if you said g("xyz") you’d end up calling g<char*>(char*) , but if you wanted to call the std::string version of g<>() you could say g<std::string>("xyz") . (Again you could also promote the argument, such as g(std::string("xyz")) , but that’s another story.)
Another time when you must specify the types is when the function takes two parameters of the same type, but you give it two different types.
Since m and n have different types, the compiler can’t deduce what type to use for T , so you have to tell it what to use:
What is a “parameterized type”?
Another way to say, “class templates.”
A parameterized type is a type that is parameterized over another type or some value. List<int> is a type ( List ) parameterized over another type ( int ).
What is “genericity”?
Yet another way to say, “class templates.”
Not to be confused with “generality” (which just means avoiding solutions which are overly specific), “genericity” means class templates.
My template function does something special when the template type T is int or std::string ; how do I write my template so it uses the special code when T is one of those specific types?
Before showing how to do this, let’s make sure you’re not shooting yourself in the foot. Does the function’s behavior appear different to your users? In other words, is the observable behavior different in some substantive way? If so, you’re probably shooting yourself in the foot and you will probably confuse your users — you’re probably better off using different functions with different names — don’t use templates, don’t use overloading. For example, if the code for int inserts something into a container and sorts the result, but the code for std::string removes something from a container and does not sort the result, those two functions ought not to be an overloaded pair — their observable behavior is different so they ought to have different names.
However if the function’s observable behavior is consistent for all the T types with the differences limited to implementation details, then you can proceed. Let’s proceed with an example of this (conceptual only; not C++):
One way to implement the above is via template specialization. Instead of a switch -statement, you end up breaking up the code into separate functions. The first function is the default case — the code to be used when T is anything other than int or std::string :
Next are the two specializations, first for the int case…
…and next for the std::string case…
That’s it; you’re done. The compiler will automagically select the correct specialization when it sees which T you are using.
Huh? Can you provide an example of template specialization that doesn’t use foo and bar ?
One of several ways I personally use template specialization is for stringification. I usually use a template to stringify various objects of various types , but I often need to specialize the code for stringifying certain specific types. For instance, when stringifying bool s I prefer "true" and "false" over "1" and "0" so I use std::boolalpha when T is bool . Also I often prefer floating point output to contain all the digits (so I can see very small differences, etc.) so I use std::setprecision when T is a floating point type. The end result usually looks something like this:
Conceptually they all do the same thing: stringify the parameter. That means the observable behavior is consistent, therefore the specializations do not confuse callers. However the details for implementing that observable behavior is slightly different for bool and floating point types, so template specialization is a good approach.
But most of the code in my template function is the same; is there some way to get the benefits of template specialization without duplicating all that source code?
For example, suppose your template function has a bunch of common code along with a relatively small amount of T -specific code (conceptual only; not C++):
If you blindly applied the advice from the FAQ on template specialization , you would end up duplicating all that code before and after the pseudo-switch statement. The way to get the best of both worlds — to get the benefits of T -specific pieces without duplicating the entire function, is to extract the pseudo-switch statement portion into a separate function foo_part() , and use template specialization on that separate function:
The main foo() function would be a simple template — no specializations. Note that the pseudo-switch statement has been replaced by a call to foo_part() :
As you can see, the body of foo() now doesn’t mention any particular T . It all gets figured out automatically. The compiler generates foo for you based on type T , and will generate the correctly typed foo_part function based on the actual compile-time known type of the x argument. Proper specializations of foo_part will be instantiated.
All those templates and template specializations must slow down my program, right?
This is a quality-of-implementation issue so your results may vary. However there is usually no slow-down at all. If anything, the templates might affect the speed of compilation slightly, but once the types are resolved by the compiler at compile-time, it will typically generate code that is just as fast as with non-template functions, including inline-expanding appropriate functions, etc.
So templates are overloading, right?
Yes and no.
Function templates participate in name resolution for overloaded functions, but the rules are different. For a template to be considered in overload resolution, the type has to match exactly. If the types do not match exactly, the conversions are not considered and the template is simply dropped from the set of viable functions. That’s what is known as “SFINAE” — Substitution Failure Is Not An Error. Example:
In this example, foo<T> cannot be considered for the first or the second call to foo in the body of main because neither 42 nor 42.0 gives the compiler any information to deduce T . The third call, however, includes foo<T> with T = char and it wins.
Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?
If all you want to know is how to fix this situation, read the next two FAQs. But in order to understand why things are the way they are, first accept these facts:
- A template is not a class or a function. A template is a “pattern” that the compiler uses to generate a family of classes or functions .
- In order for the compiler to generate the code, it must see both the template definition (not just declaration) and the specific types/whatever used to “fill in” the template. For example, if you’re trying to use a Foo<int> , the compiler must see both the Foo template and the fact that you’re trying to make a specific Foo<int> .
- Your compiler probably doesn’t remember the details of one .cpp file while it is compiling another .cpp file. It could , but most do not and if you are reading this FAQ, it almost definitely does not. BTW this is called the “separate compilation model.”
Now based on those facts, here’s an example that shows why things are the way they are. Suppose you have a template Foo defined like this:
Along with similar definitions for the member functions:
Now suppose you have some code in file Bar.cpp that uses Foo<int> :
Clearly somebody somewhere is going to have to use the “pattern” for the constructor definition and for the someMethod() definition and instantiate those when T is actually int . But if you had put the definition of the constructor and someMethod() into file Foo.cpp , the compiler would see the template code when it compiled Foo.cpp and it would see Foo<int> when it compiled Bar.cpp , but there would never be a time when it saw both the template code and Foo<int> . So by rule #2 above, it could never generate the code for Foo<int>::someMethod() .
A note to the experts: I have obviously made several simplifications above. This was intentional so please don’t complain too loudly. If you know the difference between a .cpp file and a compilation unit, the difference between a class template and a template class, and the fact that templates really aren’t just glorified macros, then don’t complain: this particular question/answer wasn’t aimed at you to begin with. I simplified things so newbies would “get it,” even if doing so offends some experts.
Reminder: Read the next two FAQs for some solutions to this problem.
How can I avoid linker errors with my template functions?
This answer will be updated due to C++11 extern template . Watch this space for updates in the near future!!
Tell your C++ compiler which instantiations to make while it is compiling your template function’s .cpp file.
As an example, consider the header file foo.h which contains the following template function declaration:
Now suppose file foo.cpp actually defines that template function:
Suppose file main.cpp uses this template function by calling foo<int>() :
If you compile and (try to) link these two .cpp files, most compilers will generate linker errors. There are two solutions for this. The first solution is to physically move the definition of the template function into the .h file, even if it is not an inline function. This solution may (or may not!) cause significant code bloat, meaning your executable size may increase dramatically (or, if your compiler is smart enough, may not; try it and see).
The other solution is to leave the definition of the template function in the .cpp file and simply add the line template void foo<int>(); to that file:
If you can’t modify foo.cpp , simply create a new .cpp file such as foo-impl.cpp as follows:
Notice that foo-impl.cpp #include s a .cpp file, not a .h file. If that’s confusing, click your heels twice, think of Kansas, and repeat after me, “I will do it anyway even though it’s confusing.” You can trust me on this one. But if you don’t trust me or are simply curious, the rationale is given earlier .
How does the C++ keyword export help with template linker errors?
The C++ keyword export was originally designed to eliminate the need to include a template definition (either by providing the definition in the header file or by including the implementation file). However, only a few compilers ever supported this capability, such as Comeau C++ and Sun Studio , and the general consensus was that it was not worth the trouble.
Because of that, in the C++11 standard, the export feature has been removed from the language. It remains a reserved word but it no longer has any meaning.
If you are working with a compiler that supports the export keyword, it will probably continue to support the keyword via some sort of compiler option or extension until its users migrate away from it. If you already have code that uses export , you can use a fairly simple discipline to allow your code to easily migrate if/when your compiler stops supporting it entirely. Just define your template header-files like this:
And define your non-inline functions in a source-file like this:
Then compile with -DUSE_EXPORT_KEYWORD , or whatever equivalent compiler option lets you set a preprocessor symbol like USE_COMPILER_KEYWORD , and if/when your compiler removes support for export , just remove that compiler option.
How can I avoid linker errors with my template classes?
Tell your C++ compiler which instantiations to make while it is compiling your template class’s .cpp file.
(If you’ve already read the previous FAQ, this answer is completely symmetric with that one, so you can probably skip this answer.)
As an example, consider the header file Foo.h which contains the following template class. Note that method Foo<T>::f() is inline and methods Foo<T>::g() and Foo<T>::h() are not.
Now suppose file Foo.cpp actually defines the non- inline methods Foo<T>::g() and Foo<T>::h() :
Suppose file main.cpp uses this template class by creating a Foo<int> and calling its methods:
If you compile and (try to) link these two .cpp files, most compilers will generate linker errors. There are two solutions for this. The first solution is to physically move the definition of the template functions into the .h file, even if they are not inline functions. This solution may (or may not!) cause significant code bloat, meaning your executable size may increase dramatically (or, if your compiler is smart enough, may not; try it and see).
The other solution is to leave the definition of the template function in the .cpp file and simply add the line template class Foo<int>; to that file:
If you can’t modify Foo.cpp , simply create a new .cpp file such as Foo-impl.cpp as follows:
Notice that Foo-impl.cpp #include s a .cpp file, not a .h file. If that’s confusing, click your heels twice, think of Kansas, and repeat after me, “I will do it anyway even though it’s confusing.” You can trust me on this one. But if you don’t trust me or are simply curious, the rationale is given earlier .
If you are using Comeau C++ , you probably want to learn about the export keyword .
Why do I get linker errors when I use template friends?
Ah, the intricacies of template friends. Here’s an example of what people often want to do:
Naturally the template will need to actually be used somewhere:
And of course the various member and friend functions will need to be defined somewhere:
The snag happens when the compiler sees the friend lines way up in the class definition proper. At that moment it does not yet know the friend functions are themselves templates; it assumes they are non-templates like this:
When you call the operator+ or operator<< functions, this assumption causes the compiler to generate a call to the non -template functions, but the linker will give you an “undefined external” error because you never actually defined those non -template functions.
The solution is to convince the compiler while it is examining the class body proper that the operator+ and operator<< functions are themselves templates. There are several ways to do this; one simple approach is pre-declare each template friend function above the definition of template class Foo :
Also you add <> in the friend lines, as shown:
After the compiler sees that magic stuff, it will be better informed about the friend functions. In particular, it will realize that the friend lines are referring to functions that are themselves templates. That eliminates the confusion.
Another approach is to define the friend function within the class body at the same moment you declare it to be a friend . For example:
Why can’t I define constraints for my template parameters?
(Note: This FAQ is a bit dated and needs to be updated for static_assert .)
Well, you can, and it’s quite easy and general.
If there is a type error, it will be in the resolution of the fairly complicated for_each() call. For example, if the element type of the container is an int , then we get some kind of obscure error related to the for_each() call (because we can’t invoke Shape::draw() for an int ).
To catch such errors early, you can write:
The initialization of the spurious variable p will trigger a comprehensible error message from most current compilers. Tricks like this are common in all languages and have to be developed for all novel constructs. In production code, you’d probably write something like:
This makes it clear that you’re making an assertion. The Can_copy template can be defined like this:
Can_copy checks (at compile time) that a T1 can be assigned to a T2 . Can_copy<T,Shape*> checks that T is a Shape* or a pointer to a class publicly derived from Shape or a type with a user-defined conversion to Shape* . Note that the definition is close to minimal:
- one line to name the constraints to be checked and the types for which to check them
- one line to list the specific constraints checked (the constraints() function)
- one line to provide a way to trigger the check (the constructor)
Note also that the definition has the desirable properties that
- You can express constraints without declaring or copying variables, thus the writer of a constraint doesn’t have to make assumptions about how a type is initialized, whether objects can be copied, destroyed, etc. (unless, of course, those are the properties being tested by the constraint)
- No code is generated for a constraint using current compilers
- No macros are needed to define or use constraints
Current compilers give acceptable error messages for a failed constraint, including the word “constraints” (to give the reader a clue), the name of the constraints, and the specific error that caused the failure (e.g. “cannot initialize Shape* by double* ”)
So why is something like Can_copy() – or something even more elegant – not in the language? A way to specify these constraints directly is being worked on as we speak – see Concepts Lite .
Until then, the above the idea is very general. After all, when we write a template we have the full expressive power of C++ available. Consider:
Actually, Derived_from doesn’t check derivation, but conversion, but that’s often a better constraint. Finding good names for constraints can be hard.
How can any human hope to understand these overly verbose template-based error messages?
Compiler error messages have got much better in recent years, and show human-readable typedefs, as well as highlighting where in the source-code the error occurred.
If you’re still using an older compiler, here’s a free tool that transforms error messages into something more understandable . The tool is no longer being developed, but worked with the following compilers: Comeau C++, Intel C++, CodeWarrior C++, GCC, Borland C++, Microsoft Visual C++, and EDG C++.
Here’s an example showing some unfiltered GCC error messages:
Here’s what the filtered error messages look like (note: you can configure the tool so it shows more information; this output was generated with settings to strip things down to a minimum):
Here is the source code to generate the above example:
Why am I getting errors when my template uses a nested type?
Perhaps surprisingly, the following code is not valid C++, even though some compilers accept it:
The reason is that in theory the function template could be called with a type that has a data member or a member function called iterator . When the compiler is parsing the template contains it doesn’t know anything about the types it will be passed by the code that comes later. This means that until the compiler knows what Container is and what members it has, there’s no way to know whether Container::iterator is a type or not. In fact, the rules of C++ say that until told otherwise, the compiler must assume Container::iterator is not a type. The solution is to give the compiler a hint via the typename keyword:
This tells the compiler that when the function template is used later its argument will always be something for which Container::iterator is a type. (And if you actually try to call it with a type where iterator is a data member or something else, you will get an error).
Why am I getting errors when my template-derived-class uses a nested type it inherits from its template-base-class?
This might hurt your head; better if you sit down.
Within D<T>::g() , name Xyz and Pqr do not depend on template parameter T , so they are known as a nondependent names . On the other hand, B<T> is dependent on template parameter T so B<T> is called a dependent name .
Here’s the rule: the compiler does not look in dependent base classes (like B<T> ) when looking up nondependent names (like Xyz or Pqr ). As a result, the compiler does not know they even exist let alone are types.
At this point, programmers sometimes prefix them with B<T>:: , such as:
Unfortunately this doesn’t work either because those names (are you ready? are you sitting down?) are not necessarily types. “Huh?!?” you say. “Not types?!?” you exclaim. “That’s crazy; any fool can SEE they are types; just look!!!” you protest. Sorry, the fact is that they might not be types. The reason is that there can be a specialization of B<T> , say B<Foo> , where B<Foo>::Xyz is a data member, for example. Because of this potential specialization, the compiler cannot assume that B<T>::Xyz is a type until it knows T . The solution is to give the compiler a hint via the typename keyword:
Why am I getting errors when my template-derived-class uses a member it inherits from its template-base-class?
Within D<T>::g() , the name f does not depend on template parameter T , so f is known as a nondependent name . On the other hand, B<T> is dependent on template parameter T so B<T> is called a dependent name .
Here’s the rule: the compiler does not look in dependent base classes (like B<T> ) when looking up nondependent names (like f ).
This doesn’t mean that inheritance doesn’t work. Class D<int> is still derived from class B<int> , the compiler still lets you implicitly do the is-a conversions (e.g., D<int>* to B<int>* ), dynamic binding still works when virtual functions are invoked, etc. But there is an issue about how names are looked up.
Workarounds:
- Change the call from f() to this->f() . Since this is always implicitly dependent in a template, this->f is dependent and the lookup is therefore deferred until the template is actually instantiated, at which point all base classes are considered.
- Insert using B<T>::f; just prior to calling f() .
- Change the call from f() to B<T>::f() . Note however that this might not give you what you want if f() is virtual, since it inhibits the virtual dispatch mechanism.
Can the previous problem hurt me silently? Is it possible that the compiler will silently generate the wrong code?
Since non-dependent types and non-dependent members are not found in the dependent template base-classes, the compiler will search the enclosing scope, such as the enclosing namespace. This can cause it to silently(!) do the wrong thing.
For example:
The use of Xyz and f within D<T>::g() will silently(!) resolve to the global entities rather than those inherited from class B<T> .
You have been warned.
How can I create a container-template that allows my users to supply the type of the underlying container that actually stores the values?
First, let’s clarify the question: the goal is to create a template Foo<> , but having the template parameter-list include some particular type of std::vector<T> or std::list<T> or some other (possibly non-standard) container to actually store the values.
Here’s one way to do that:
If you want to allow your users to provide you with an underlying container that does not necessarily have a value_type typedef (such as some container from a third party), you could provide the value-type explicitly:
However you cannot (yet) provide an unspecified template as a template parameter, such as this:
Follow-up to previous: can I pass in the underlying structure and the element-type separately?
Yes, with a “proxy” trick.
Here’s the problem: std::vector template can have, does have, more than one argument. You’re required to make them match in the number, order, and nature — type/non-type, etc.
It is possible, however, to “cheat” your way out of specifying all those arguments and use the defaults. It’s called the “proxy template” technique:
You can also create a proxy if you actually have a template that takes only one argument:
The “template typedefs” proposal will allow redefining templates just like we do with types, which will make the proxy-trick unnecessary. Until then, use something like the above.
Related: all those proxies must negatively reflect on the speed of my program. Don’t they?
They might require an extra microsecond to compile, but once all the types are resolved by the compiler, the resulting code is just as fast as if you used them directly without any proxy templates whatsoever.
Not only that, there are some techniques (template meta programming or TMP) that can, under the right circumstances, improve the efficiency of the generated code. The basic notion is to get the compiler to do more work at compile-time so less work has to be done at runtime.
Please Login to submit a recommendation.
If you don’t have an account, you can register for free.
26.1 — Template classes
In a previous chapter, we covered function templates ( 11.6 -- Function templates ), which allow us to generalize functions to work with many different data types. While this is a great start down the road to generalized programming, it doesn’t solve all of our problems. Let’s take a look at an example of one such problem, and see what templates can further do for us.
Templates and container classes
In the lesson on 23.6 -- Container classes , you learned how to use composition to implement classes that contained multiple instances of other classes. As one example of such a container, we took a look at the IntArray class. Here is a simplified example of that class:
While this class provides an easy way to create arrays of integers, what if we want to create an array of doubles? Using traditional programming methods, we’d have to create an entirely new class! Here’s an example of DoubleArray, an array class used to hold doubles.
Although the code listings are lengthy, you’ll note the two classes are almost identical! In fact, the only substantive difference is the contained data type (int vs double). As you likely have guessed, this is another area where templates can be put to good use, to free us from having to create classes that are bound to one specific data type.
Creating template classes works pretty much identically to creating template functions, so we’ll proceed by example. Here’s our array class, templated version:
As you can see, this version is almost identical to the IntArray version, except we’ve added the template declaration, and changed the contained data type from int to T.
Note that we’ve also defined the operator[] function outside of the class declaration. This isn’t necessary, but new programmers typically stumble when trying to do this for the first time due to the syntax, so an example is instructive. Each templated member function defined outside the class declaration needs its own template declaration. Also, note that the name of the templated array class is Array<T>, not Array -- Array would refer to a non-templated version of a class named Array, unless Array is used inside of the class. For example, the copy constructor and copy-assignment operator used Array rather than Array<T>. When the class name is used without template arguments inside of the class, the arguments are the same as the ones of the current instantiation.
Here’s a short example using the above templated array class:
This example prints the following:
Template classes are instantiated in the same way template functions are -- the compiler stencils out a copy upon demand, with the template parameter replaced by the actual data type the user needs, and then compiles the copy. If you don’t ever use a template class, the compiler won’t even compile it.
Template classes are ideal for implementing container classes, because it is highly desirable to have containers work across a wide variety of data types, and templates allow you to do so without duplicating code. Although the syntax is ugly, and the error messages can be cryptic, template classes are truly one of C++’s best and most useful features.
Splitting up template classes
A template is not a class or a function -- it is a stencil used to create classes or functions. As such, it does not work in quite the same way as normal functions or classes. In most cases, this isn’t much of a issue. However, there is one area that commonly causes problems for developers.
With non-template classes, the common procedure is to put the class definition in a header file, and the member function definitions in a similarly named code file. In this way, the member function definitions are compiled as a separate project file. However, with templates, this does not work. Consider the following:
The above program will compile, but cause a linker error:
Just like with function templates, the compiler will only instantiate a class template if the class template is used (e.g. as the type of an object like intArray) in a translation unit. In order to perform the instantiation, the compiler must see both the full class template definition (not just a declaration) and the specific template type(s) needed.
Also remember that C++ compiles files individually. When main.cpp is compiled, the contents of the Array.h header (including the template class definition) are copied into main.cpp. When the compiler sees that we need two template instances, Array<int>, and Array<double>, it will instantiate these, and compile them as part of the main.cpp translation unit. Because the operator[] member function has a declaration, the compiler will accept a call to it, assuming it will be defined elsewhere.
When Array.cpp is compiled separately, the contents of the Array.h header are copied into Array.cpp, but the compiler won’t find any code in Array.cpp that requires the Array class template or Array<int>::operator[] function template to be instantiated -- so it won’t instantiate anything.
Thus, when the program is linked, we’ll get a linker error, because main.cpp made a call to Array<int>::operator[] but that template function was never instantiated!
There are quite a few ways to work around this.
The easiest way is to simply put all of your template class code in the header file (in this case, put the contents of Array.cpp into Array.h, below the class). In this way, when you #include the header, all of the template code will be in one place. The upside of this solution is that it is simple. The downside here is that if the template class is used in many files, you will end up with many local instances of the template class, which can increase your compile and link times (your linker should remove the duplicate definitions, so it shouldn’t bloat your executable). This is our preferred solution unless the compile or link times start to become a problem.
If you feel that putting the Array.cpp code into the Array.h header makes the header too long/messy, an alternative is to move the contents of Array.cpp to a new file named Array.inl (.inl stands for inline), and then include Array.inl at the bottom of the Array.h header (inside the header guard). That yields the same result as putting all the code in the header, but helps keep things a little more organized.
If you use the .inl method and then get a compiler error about duplicate definitions, your compiler is most likely compiling the .inl file as part of the project as if it were a code file. This results in the contents of the .inl getting compiled twice: once when your compiler compiles the .inl, and once when the .cpp file that includes the .inl gets compiled. If the .inl file contains any non-inline functions (or variables), then we will run afoul of the one definition rule. If this happens, you’ll need to exclude the .inl file from being compiled as part of the build.
Excluding the .inl from the build can usually be done by right clicking on the .inl file in the project view, and then choosing properties. The setting will be somewhere in there. In Visual Studio, set “Exclude From Build” to “Yes”. In Code::Blocks, uncheck “Compile file” and “Link file”.
Other solutions involve #including .cpp files, but we don’t recommend these because of the non-standard usage of #include.
Another alternative is to use a three-file approach. The template class definition goes in the header. The template class member functions goes in the code file. Then you add a third file, which contains all of the instantiated classes you need:
templates.cpp:
The “template class” command causes the compiler to explicitly instantiate the template class. In the above case, the compiler will stencil out definitions for Array<int> and Array<double> inside of templates.cpp. Other code files that want to use these types can include Array.h (to satisfy the compiler), and the linker will link in these explicit type definitions from template.cpp.
This method may be more efficient (depending on how your compiler and linker handle templates and duplicate definitions), but requires maintaining the templates.cpp file for each program.
cppreference.com
Template parameters and template arguments, [ edit ] template parameters.
Every template is parameterized by one or more template parameters, indicated in the parameter-list of the template declaration syntax:
Each parameter in parameter-list may be:
- a non-type template parameter;
- a type template parameter;
- a template template parameter.
[ edit ] Non-type template parameter
A structural type is one of the following types (optionally cv-qualified, the qualifiers are ignored):
- lvalue reference type (to object or to function);
- an integral type ;
- a pointer type (to object or to function);
- a pointer to member type (to member object or to member function);
- an enumeration type ;
Array and function types may be written in a template declaration, but they are automatically replaced by pointer to object and pointer to function as appropriate.
When the name of a non-type template parameter is used in an expression within the body of the class template, it is an unmodifiable prvalue unless its type was an lvalue reference type , or unless its type is a class type (since C++20) .
A template parameter of the form class Foo is not an unnamed non-type template parameter of type Foo , even if otherwise class Foo is an elaborated type specifier and class Foo x ; declares x to be of type Foo .
[ edit ] Type template parameter
The name of the parameter is optional:
In the body of the template declaration, the name of a type parameter is a typedef-name which aliases the type supplied when the template is instantiated.
[ edit ] Template template parameter
In the body of the template declaration, the name of this parameter is a template-name (and needs arguments to be instantiated).
[ edit ] Name resolution for template parameters
The name of a template parameter is not allowed to be redeclared within its scope (including nested scopes). A template parameter is not allowed to have the same name as the template name.
In the definition of a member of a class template that appears outside of the class template definition, the name of a member of the class template hides the name of a template parameter of any enclosing class templates, but not a template parameter of the member if the member is a class or function template.
In the definition of a member of a class template that appears outside of the namespace containing the class template definition, the name of a template parameter hides the name of a member of this namespace.
In the definition of a class template or in the definition of a member of such a template that appears outside of the template definition, for each non- dependent base class, if the name of the base class or the name of a member of the base class is the same as the name of a template parameter, the base class name or member name hides the template parameter name.
[ edit ] Template arguments
In order for a template to be instantiated, every template parameter (type, non-type, or template) must be replaced by a corresponding template argument. For class templates , the arguments are either explicitly provided , deduced from the initializer , (since C++17) or defaulted. For function templates , the arguments are explicitly provided, deduced from the context , or defaulted.
If an argument can be interpreted as both a type-id and an expression, it is always interpreted as a type-id, even if the corresponding template parameter is non-type:
[ edit ] Template non-type arguments
Given the type of the non-type template parameter declaration as T .
The value of a non-type template parameter P of (possibly deduced) (since C++17) type T is determined from its template argument A as follows:
[ edit ] Template type arguments
A template argument for a type template parameter must be a type-id , which may name an incomplete type:
[ edit ] Template template arguments
A template argument for a template template parameter must be an id-expression which names a class template or a template alias.
When the argument is a class template, only the primary template is considered when matching the parameter. The partial specializations, if any, are only considered when a specialization based on this template template parameter happens to be instantiated.
To match a template template argument A to a template template parameter P , P must be at least as specialized as A (see below). If P 's parameter list includes a parameter pack , zero or more template parameters (or parameter packs) from A 's template parameter list are matched by it. (since C++11)
Formally, a template template-parameter P is at least as specialized as a template template argument A if, given the following rewrite to two function templates, the function template corresponding to P is at least as specialized as the function template corresponding to A according to the partial ordering rules for function templates . Given an invented class template X with the template parameter list of A (including default arguments):
- Each of the two function templates has the same template parameters, respectively, as P or A .
- Each function template has a single function parameter whose type is a specialization of X with template arguments corresponding to the template parameters from the respective function template where, for each template parameter PP in the template parameter list of the function template, a corresponding template argument AA is formed. If PP declares a parameter pack, then AA is the pack expansion PP... ; otherwise, (since C++11) AA is the id-expression PP .
If the rewrite produces an invalid type, then P is not at least as specialized as A .
Before the adoption of P0522R0 , each of the template parameters of A must match corresponding template parameters of P exactly. This hinders many reasonable template argument from being accepted.
Although it was pointed out very early ( CWG#150 ), by the time it was resolved, the changes were applied to the C++17 working paper and the resolution became a de facto C++17 feature. Many compilers disable it by default:
- GCC disables it in all language modes prior to C++17 by default, it can only be enabled by setting a compiler flag in these modes.
- Clang disables it in all language modes by default, it can only be enabled by setting a compiler flag.
- Microsoft Visual Studio treats it as a normal C++17 feature and only enables it in C++17 and later language modes (i.e. no support in C++14 language mode, which is the default mode).
[ edit ] Default template arguments
Default template arguments are specified in the parameter lists after the = sign. Defaults can be specified for any kind of template parameter (type, non-type, or template) , but not to parameter packs (since C++11) .
If the default is specified for a template parameter of a primary class template , primary variable template, (since C++14) or alias template, each subsequent template parameter must have a default argument , except the very last one may be a template parameter pack (since C++11) . In a function template, there are no restrictions on the parameters that follow a default , and a parameter pack may be followed by more type parameters only if they have defaults or can be deduced from the function arguments (since C++11) .
Default parameters are not allowed
- in the out-of-class definition of a member of a class template (they have to be provided in the declaration inside the class body). Note that member templates of non-template classes can use default parameters in their out-of-class definitions (see GCC bug 53856 )
- in friend class template declarations
Default template arguments that appear in the declarations are merged similarly to default function arguments:
But the same parameter cannot be given default arguments twice in the same scope:
When parsing a default template argument for a non-type template parameter, the first non-nested > is taken as the end of the template parameter list rather than a greater-than operator:
The template parameter lists of template template parameters can have their own default arguments, which are only in effect where the template template parameter itself is in scope:
Member access for the names used in a default template parameter is checked at the declaration, not at the point of use:
[ edit ] Template argument equivalence
Template argument equivalence is used to determine whether two template identifiers are same.
Two values are template-argument-equivalent if they are of the same type and any of the following conditions is satisfied:
- They are of integral or enumeration type and their values are the same.
- They are of pointer type and they have the same pointer value.
- They are of pointer-to-member type and they refer to the same class member or are both the null member pointer value.
- They are of lvalue reference type and they refer to the same object or function.
[ edit ] Notes
[ edit ] examples, [ edit ] defect reports.
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
- Todo with reason
- Pages with unreviewed CWG DR marker
- Recent changes
- Offline version
- What links here
- Related changes
- Upload file
- Special pages
- Printable version
- Permanent link
- Page information
- In other languages
- This page was last modified on 16 July 2024, at 21:02.
- Privacy policy
- About cppreference.com
- Disclaimers
IMAGES
VIDEO
COMMENTS
template <typename U>. Wrapper &operator=(Wrapper<U> &rhs) {. cout << "2" << endl; return *this; I then declare a and b: assigning b to a will use the non-const templated assignment operator overload from above, and the number "2" is displayed. What puzzles me is this: If I declare c and d, and assign d to c, neither of the two assignment ...
Class Template Arguments Deduction (C++17 Onwards) The class template argument deduction was added in C++17 and has since been part of the language. It allows us to create the class template instances without explicitly definition the types just like function templates. Example: In the following example, we demonstrate how the compiler ...
externtemplateclass-keytemplate-name<argument-list>; (2) (since C++11) class-key. -. class, struct or union. 1) Explicit instantiation definition. 2) Explicit instantiation declaration. An explicit instantiation definition forces instantiation of the class, struct, or union they refer to.
C++ Templates. Templates are a way to allow functions and classes to use the same code for many different data types. To declare a template you use the template keyword followed by a list of template parameters in angle brackets: template <parameter1, parameter2, parameter3>. Immediately after the template declaration, you write a function or ...
C++ 17 introduced many new ways to declare a variable. Earlier assignment and declaration was done using "=" Example: int a = 5; But now 2 more ways are introduced in C++17. They are: Constructor initialization: In this way, the value of the variable is enclosed in parentheses ( () ). In this way, value can be passed in two ways shown below. #inclu
When working with template classes in C++, especially those involving inheritance, you might encounter unexpected behaviors with assignment operators. One such scenario arises when using the keyword using to inherit an assignment operator that does not work as expected. In this post, we'll delve into why this might happen, particularly focusing ...
A template is not a class or a function. A template is a “pattern” that the compiler uses to generate a family of classes or functions. In order for the compiler to generate the code, it must see both the template definition (not just declaration) and the specific types/whatever used to “fill in” the template.
Template declarations (class, function, and variables (since C++14)) can appear inside a member specification of any class, struct, or union that are not local classes. Partial specializations of member template may appear both at class scope and at enclosing namespace scope. Explicit specializations may appear in any scope in which the primary ...
26.1 — Template classes. In a previous chapter, we covered function templates (11.6 -- Function templates), which allow us to generalize functions to work with many different data types. While this is a great start down the road to generalized programming, it doesn’t solve all of our problems.
Every template is parameterized by one or more template parameters, indicated in the parameter-list of the template declaration syntax: template<parameter-list>declaration. (1) template<parameter-list>requiresconstraintdeclaration. (2) (since C++20) Each parameter in parameter-list may be: a non-type template parameter;