{"id":6143,"date":"2021-05-19T20:33:29","date_gmt":"2021-05-19T20:33:29","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/class-templates\/"},"modified":"2021-05-19T20:33:29","modified_gmt":"2021-05-19T20:33:29","slug":"class-templates","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/class-templates\/","title":{"rendered":"Class Templates"},"content":{"rendered":"<p>A function template represents a family of functions. Accordingly, a class template represents a family of classes. Today, I want to introduce class templates.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6140\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/ClassTemplate.png\" alt=\"ClassTemplate\" width=\"650\" height=\"388\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/ClassTemplate.png 917w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/ClassTemplate-300x179.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/ClassTemplate-768x459.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>Defining a class template is straightforward.<\/p>\n<\/p>\n<h2>Definition of a Class Template<\/h2>\n<p>Assume you have a class A<code>rray<\/code> that should become a class template.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>{\r\n \r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n<span style=\"color: #555555;\"><\/span>    <span style=\"color: #007788; font-weight: bold;\">int<\/span> getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #ff6600;\">10<\/span>;\r\n    }\r\n\r\n <span style=\"color: #9999ff;\">private:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> elem[<span style=\"color: #ff6600;\">10<\/span>];\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The class <code>Array<\/code> holds a C-array of int with length 10. The type of the C-array and its length are obvious generalization points. Let&#8217;s make a class template by introducing a type parameter<code> T<\/code> and a non-type parameter <code>N<\/code> and playing with them.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ arrayClassTemplate.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;cstddef&gt;                     <\/span><span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>{\r\n\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n<span style=\"color: #555555;\"><\/span>    <span style=\"color: #007788; font-weight: bold;\">std::size_t<\/span> getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> N;\r\n    }\r\n\r\n<span style=\"color: #9999ff;\">private:<\/span>\r\n    T elem[N];\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    Array<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, <span style=\"color: #ff6600;\">100<\/span><span style=\"color: #555555;\">&gt;<\/span> intArr;             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"intArr.getSize(): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> intArr.getSize() <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    Array<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>string, <span style=\"color: #ff6600;\">5<\/span><span style=\"color: #555555;\">&gt;<\/span> strArr;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"strArr.getSize(): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> strArr.getSize() <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    Array<span style=\"color: #555555;\">&lt;<\/span>Array<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, <span style=\"color: #ff6600;\">3<\/span><span style=\"color: #555555;\">&gt;<\/span>, <span style=\"color: #ff6600;\">25<\/span><span style=\"color: #555555;\">&gt;<\/span> intArrArr; <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"intArrArr.getSize(): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> intArrArr.getSize() <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The <code>Array<\/code> is parametrized by its type and its size. For size, I used the unsigned integer type <code>std::size_t<\/code> (2) that can store the maximum size. To use <code>std::size_t<\/code>I have to include the header <code>&lt;cstddef&gt; <\/code>(1). So far, the <code>Array<\/code> can be instantiated with an <code>int<\/code> (3) with a <code>std::string<\/code> (4), and with an <code>Array&lt;int, 3&gt;<\/code> (5). The following screenshot shows the output of the program.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6141\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/arrayClassTemplate.png\" alt=\"arrayClassTemplate\" width=\"400\" height=\"209\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/arrayClassTemplate.png 462w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/arrayClassTemplate-300x157.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>You can define the member functions of a template inside and outside the class template.<\/p>\n<h3>Definitions of Member Functions<\/h3>\n<p>Defining the member function inside the class template <code><\/code>is straightforward.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>   <span style=\"color: #0099ff; font-style: italic;\"><\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>{\r\n\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">std::size_t<\/span> getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> N;\r\n    }\r\n\r\n<span style=\"color: #9999ff;\">private:<\/span>\r\n    T elem[N];\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>When you define the member functions outside the class, you have to specify that it is a template, and you have to specify the full type qualification of the class template. Here is the modified class template <code>Array<\/code>:<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span> \r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>{\r\n\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">std::sizt_<\/span> getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span>;\r\n\r\n<span style=\"color: #9999ff;\">private:<\/span>\r\n    T elem[N];\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">std::size_t<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;::<\/span>getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> N;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>(1) is the member function <code>getSize<\/code> of the <code>Array<\/code>, defined outside the class. Defining the member function outside the class template becomes challenging if the member function itself is a template.<\/p>\n<h3>Member Functions as Templates<\/h3>\n<p>A typical example of a generic member function is a templated assignment operator. The reason is straightforward. You want to assign an<code> Array&lt;T, N&gt;<\/code> to an <code>Array&lt;T2, N2&gt;<\/code> if <code>T<\/code> is assignable to<code> T2<\/code> and both arrays have the same size.<\/p>\n<p>Assigning an <code>Array&lt;float, 5&gt;<\/code> to an <code>Array&lt;double, 5&gt;<\/code> is not valid because both arrays have different types.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ arrayAssignmentError.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;cstddef&gt;                     <\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>   \r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>{\r\n\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">std::size_t<\/span> getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> N;\r\n    }\r\n\r\n<span style=\"color: #9999ff;\">private:<\/span>\r\n    T elem[N];\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    Array<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">float<\/span>, <span style=\"color: #ff6600;\">5<\/span><span style=\"color: #555555;\">&gt;<\/span> floatArr;  \r\n    Array<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">float<\/span>, <span style=\"color: #ff6600;\">5<\/span><span style=\"color: #555555;\">&gt;<\/span> floatArr2;\r\n    \r\n    floatArr2 <span style=\"color: #555555;\">=<\/span> floatArr;             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n     \r\n    \r\n    Array<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">double<\/span>, <span style=\"color: #ff6600;\">5<\/span><span style=\"color: #555555;\">&gt;<\/span> doubleArr;       \r\n    doubleArr <span style=\"color: #555555;\">=<\/span> floatArr;             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n    \r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Assigning <code>floatArr<\/code> to <code>floatArr2<\/code> (1) is valid because both arrays have the same type. Assigning <code>floatArr<\/code> to <code>doubleArr<\/code> is an error (2) because both classes have different types. The compiler consequently complains that there is no conversion from<code> Array&lt;float, 5&gt;<\/code> to an<code> Array&lt;double, 5&gt;. <\/code><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6142\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/arrayAssignmentError.png\" alt=\"arrayAssignmentError\" width=\"700\" height=\"191\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/arrayAssignmentError.png 1295w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/arrayAssignmentError-300x82.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/arrayAssignmentError-1024x280.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/05\/arrayAssignmentError-768x210.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>Here is a naive implementation of the class Array that supports the assignment of two arrays of the same length. The C-array <code>elem<\/code> is intentionally public.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>   \r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>{\r\n\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T2<span style=\"color: #555555;\">&gt;<\/span>\r\n    Array<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;&amp;<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">=<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T2, N<span style=\"color: #555555;\">&gt;&amp;<\/span> arr) {\r\n        std<span style=\"color: #555555;\">::<\/span>copy(std<span style=\"color: #555555;\">::<\/span>begin(arr.elem), std<span style=\"color: #555555;\">::<\/span>end(arr.elem), std<span style=\"color: #555555;\">::<\/span>begin(elem));\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #555555;\">*<\/span><span style=\"color: #006699; font-weight: bold;\">this<\/span>;\r\n    }\r\n    <span style=\"color: #007788; font-weight: bold;\">std::size_t<\/span> getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> N;\r\n    }\r\n    T elem[N];\r\n    \r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The assignment operator<code> Array&lt;T, N&gt;&amp; operator = (const Array&lt;T2, N&gt;&amp; arr)<\/code> accepts arrays that could vary in the underlying type but could not vary in length.&nbsp; Before I show the code in action, I want to improve it.<\/p>\n<h4>Friendship<\/h4>\n<p>To make <code>elem<\/code> private, it must be a friend of the class.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>   \r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>{\r\n\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T2<span style=\"color: #555555;\">&gt;<\/span>\r\n    Array<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;&amp;<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">=<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T2, N<span style=\"color: #555555;\">&gt;&amp;<\/span> arr) {\r\n        std<span style=\"color: #555555;\">::<\/span>copy(std<span style=\"color: #555555;\">::<\/span>begin(arr.elem), std<span style=\"color: #555555;\">::<\/span>end(arr.elem), std<span style=\"color: #555555;\">::<\/span>begin(elem));\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #555555;\">*<\/span><span style=\"color: #006699; font-weight: bold;\">this<\/span>;\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span>, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span><span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #006699; font-weight: bold;\">friend<\/span> <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>;          <span style=\"color: #0099ff;\">\/\/ (1)<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">std::size_t<\/span> getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> N;\r\n    }\r\n <span style=\"color: #9999ff;\">private:<\/span>\r\n    T elem[N];\r\n    \r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The line <code>template&lt;typename, std::size_t&gt; friend class Array <\/code>(1) declares all instances of Array to friends.<\/p>\n<h4>Member Function defined Outside The Class<\/h4>\n<p>Defining the generic member function outside the class is quite a job.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>   \r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>{\r\n\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T2<span style=\"color: #555555;\">&gt;<\/span>\r\n    Array<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;&amp;<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">=<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T2, N<span style=\"color: #555555;\">&gt;&amp;<\/span> arr);\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span>, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span><span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #006699; font-weight: bold;\">friend<\/span> <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>;\r\n    <span style=\"color: #007788; font-weight: bold;\">std::size_t<\/span> getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span>;\r\n <span style=\"color: #9999ff;\">private:<\/span>\r\n    T elem[N];\r\n    \r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span> \r\n<span style=\"color: #007788; font-weight: bold;\">std::size_t<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;::<\/span>getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span> { <span style=\"color: #006699; font-weight: bold;\">return<\/span> N; }\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;                <span style=\"color: #0099ff;\">\/\/ (1)<\/span><\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T2<span style=\"color: #555555;\">&gt;<\/span>\r\nArray<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;&amp;<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;::<\/span><span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">=<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T2, N<span style=\"color: #555555;\">&gt;&amp;<\/span> arr) {\r\n    std<span style=\"color: #555555;\">::<\/span>copy(std<span style=\"color: #555555;\">::<\/span>begin(arr.elem), std<span style=\"color: #555555;\">::<\/span>end(arr.elem), std<span style=\"color: #555555;\">::<\/span>begin(elem));\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #555555;\">*<\/span><span style=\"color: #006699; font-weight: bold;\">this<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>In this case, you define a generic member function (1) outside the class body; you have to specify that the class and the member functions are templates. Additionally, you have to specify the full type qualification of the generic member function. So far, the assignment operator is used for types<code> T<\/code> and <code>T2<\/code> that is not convertible. Invoking the assignment operator with non-convertible types gives an ugly error message. I should fix this.<\/p>\n<h4>Requirements on the Type Parameters<\/h4>\n<p>The requirements can be formulated with the <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/header\/type_traits\">type traits library<\/a> and <code>static_assert<\/code> (C++11), or with concepts (C++20). Here are the two variations of the generic assignment operator:<\/p>\n<ul>\n<li>C++11<\/li>\n<\/ul>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T2<span style=\"color: #555555;\">&gt;<\/span>\r\nArray<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;&amp;<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;::<\/span><span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">=<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T2, N<span style=\"color: #555555;\">&gt;&amp;<\/span> arr) {\r\n    static_assert(std<span style=\"color: #555555;\">::<\/span>is_convertible<span style=\"color: #555555;\">&lt;<\/span>T2, T<span style=\"color: #555555;\">&gt;::<\/span>value,     <span style=\"color: #0000ff;\"><\/span><span style=\"color: #3366ff;\">\/\/ (1)<\/span>\r\n                      <span style=\"color: #cc3300;\">\"Cannot convert source type into the destination type!\"<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span>copy(std<span style=\"color: #555555;\">::<\/span>begin(arr.elem), std<span style=\"color: #555555;\">::<\/span>end(arr.elem), std<span style=\"color: #555555;\">::<\/span>begin(elem));\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #555555;\">*<\/span><span style=\"color: #006699; font-weight: bold;\">this<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<ul>\n<li>C++20<\/li>\n<\/ul>\n<p>Finally, here is the complete program using the concept <code>std::convertible_to<\/code> in the declaration (1) and the definition (2) of the member function.<span style=\"color: #0099ff; font-style: italic;\"><\/span><\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ arrayAssignment.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;algorithm&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;cstddef&gt;                     <\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;concepts&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>   \r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>{\r\n\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T2<span style=\"color: #555555;\">&gt;<\/span>\r\n    Array<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;&amp;<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">=<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T2, N<span style=\"color: #555555;\">&gt;&amp;<\/span> arr) requires std<span style=\"color: #555555;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>T2, T<span style=\"color: #555555;\">&gt;<\/span>;           <span style=\"color: #0099ff;\">\/\/ (1)<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span>, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span><span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #006699; font-weight: bold;\">friend<\/span> <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Array<\/span>;\r\n    <span style=\"color: #007788; font-weight: bold;\">std::size_t<\/span> getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span>;\r\n <span style=\"color: #9999ff;\">private:<\/span>\r\n    T elem[N];\r\n    \r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span> \r\n<span style=\"color: #007788; font-weight: bold;\">std::size_t<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;::<\/span>getSize() <span style=\"color: #006699; font-weight: bold;\">const<\/span> { <span style=\"color: #006699; font-weight: bold;\">return<\/span> N; }\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> N<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T2<span style=\"color: #555555;\">&gt;<\/span>\r\nArray<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;&amp;<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T, N<span style=\"color: #555555;\">&gt;::<\/span><span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">=<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> Array<span style=\"color: #555555;\">&lt;<\/span>T2, N<span style=\"color: #555555;\">&gt;&amp;<\/span> arr) requires std<span style=\"color: #555555;\">::<\/span>convertible_to<span style=\"color: #555555;\">&lt;<\/span>T2, T<span style=\"color: #555555;\">&gt;<\/span> {<span style=\"color: #0099ff;\"> \/\/ (2)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>copy(std<span style=\"color: #555555;\">::<\/span>begin(arr.elem), std<span style=\"color: #555555;\">::<\/span>end(arr.elem), std<span style=\"color: #555555;\">::<\/span>begin(elem));\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #555555;\">*<\/span><span style=\"color: #006699; font-weight: bold;\">this<\/span>;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> main() {\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    Array<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">float<\/span>, <span style=\"color: #ff6600;\">5<\/span><span style=\"color: #555555;\">&gt;<\/span> floatArr;  \r\n    Array<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">float<\/span>, <span style=\"color: #ff6600;\">5<\/span><span style=\"color: #555555;\">&gt;<\/span> floatArr2;\r\n    floatArr.getSize();\r\n    \r\n    floatArr2 <span style=\"color: #555555;\">=<\/span> floatArr;             <span style=\"color: #0099ff; font-style: italic;\"><\/span>\r\n     \r\n    \r\n    Array<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">double<\/span>, <span style=\"color: #ff6600;\">5<\/span><span style=\"color: #555555;\">&gt;<\/span> doubleArr;       \r\n    doubleArr <span style=\"color: #555555;\">=<\/span> floatArr;             <span style=\"color: #0099ff; font-style: italic;\"><\/span>\r\n\r\n    Array<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>string, <span style=\"color: #ff6600;\">5<\/span><span style=\"color: #555555;\">&gt;<\/span> strArr;\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ doubleArr = strArr;            \/\/ (3)<\/span>\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>When I enable (3), the GCC complains that the constraints are unsatisfied. <code><br \/><\/code><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>As you might imagine. I&#8217;m not done with class templates.<a href=\"https:\/\/www.modernescpp.com\/index.php\/surprise-included-inheritance-and-member-functions-of-class-templates\"> Next time <\/a>I will write about two tricky details: the inheritance of class templates and the instantiation of member functions of class templates.<\/p>\n<h2>The Next PDF-Bundle<\/h2>\n<p>I want to resuscitate an old service and create bundles of old posts. I will create the bundles only for my English posts because this is quite a job. These bundles include the posts, all source files, and a CMake file. To make the right decision, you have to make your cross. I will build the pdf bundle with the most votes. The vote is open until 30.05 (including).<a href=\"https:\/\/www.modernescpp.com\/index.php\/which-pdf-bundle-do-you-want-make-your-choice\"> Vote here<\/a>.<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A function template represents a family of functions. Accordingly, a class template represents a family of classes. Today, I want to introduce class templates.<\/p>\n","protected":false},"author":21,"featured_media":6140,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[376],"tags":[],"class_list":["post-6143","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-templates"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6143","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=6143"}],"version-history":[{"count":0,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6143\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/6140"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}