Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is a common question in C++ programming. There are two valid answers to this. There are advantages and disadvantages to both answers and your choice will depend on context. The common answer is to put all the implementation in the header file, but there's another approach will will be suitable in some cases. The choice is yours.</p> <p>The code in a template is merely a 'pattern' known to the compiler. The compiler won't compile the constructors <code>cola&lt;float&gt;::cola(...)</code> and <code>cola&lt;string&gt;::cola(...)</code> until it is forced to do so. And we must ensure that this compilation happens for the constructors <em>at least</em> once in the entire compilation process, or we will get the 'undefined reference' error. (This applies to the other methods of <code>cola&lt;T&gt;</code> also.)</p> <h3>Understanding the problem</h3> <p>The problem is caused by the fact that <code>main.cpp</code> and <code>cola.cpp</code> will be compiled separately first. In <code>main.cpp</code>, the compiler will <em>implicitly</em> instantiate the template classes <code>cola&lt;float&gt;</code> and <code>cola&lt;string&gt;</code> because those particular instantiations are used in <code>main.cpp</code>. The bad news is that the implementations of those member functions are not in <code>main.cpp</code>, nor in any header file included in <code>main.cpp</code>, and therefore the compiler can't include complete versions of those functions in <code>main.o</code>. When compiling <code>cola.cpp</code>, the compiler won't compile those instantiations either, because there are no implicit or explicit instantiations of <code>cola&lt;float&gt;</code> or <code>cola&lt;string&gt;</code>. Remember, when compiling <code>cola.cpp</code>, the compiler has no clue which instantiations will be needed; and we can't expect it to compile for <em>every</em> type in order to ensure this problem never happens! (<code>cola&lt;int&gt;</code>, <code>cola&lt;char&gt;</code>, <code>cola&lt;ostream&gt;</code>, <code>cola&lt; cola&lt;int&gt; &gt;</code> ... and so on ...)</p> <p>The two answers are:</p> <ul> <li>Tell the compiler, at the end of <code>cola.cpp</code>, which particular template classes will be required, forcing it to compile <code>cola&lt;float&gt;</code> and <code>cola&lt;string&gt;</code>.</li> <li>Put the implementation of the member functions in a header file that will be included <em>every</em> time any other 'translation unit' (such as <code>main.cpp</code>) uses the template class.</li> </ul> <h3>Answer 1: Explicitly instantiate the template, and its member definitions</h3> <p>At the <em>end</em> of <code>cola.cpp</code>, you should add lines explicitly instantiating all the relevant templates, such as</p> <pre><code>template class cola&lt;float&gt;; template class cola&lt;string&gt;; </code></pre> <p>and you add the following two lines at the end of <code>nodo_colaypila.cpp</code>:</p> <pre><code>template class nodo_colaypila&lt;float&gt;; template class nodo_colaypila&lt;std :: string&gt;; </code></pre> <p>This will ensure that, when the compiler is compiling <code>cola.cpp</code> that it will explicitly compile all the code for the <code>cola&lt;float&gt;</code> and <code>cola&lt;string&gt;</code> classes. Similarly, <code>nodo_colaypila.cpp</code> contains the implementations of the <code>nodo_colaypila&lt;...&gt;</code> classes.</p> <p>In this approach, you should ensure that all the of the implementation is placed into one <code>.cpp</code> file (i.e. one translation unit) and that the explicit instantation is placed after the definition of all the functions (i.e. at the end of the file).</p> <h3>Answer 2: Copy the code into the relevant header file</h3> <p>The common answer is to move all the code from the implementation files <code>cola.cpp</code> and <code>nodo_colaypila.cpp</code> into <code>cola.h</code> and <code>nodo_colaypila.h</code>. In the long run, this is more flexible as it means you can use extra instantiations (e.g. <code>cola&lt;char&gt;</code>) without any more work. But it could mean the same functions are compiled many times, once in each translation unit. This is not a big problem, as the linker will correctly ignore the duplicate implementations. But it might slow down the compilation a little.</p> <h3>Summary</h3> <p>The default answer, used by the STL for example and in most of the code that any of us will write, is to put all the implementations in the header files. But in a more private project, you will have more knowledge and control of which particular template classes will be instantiated. In fact, this 'bug' might be seen as a feature, as it stops users of your code from accidentally using instantiations you have not tested for or planned for ("I know this works for <code>cola&lt;float&gt;</code> and <code>cola&lt;string&gt;</code>, if you want to use something else, tell me first and will can verify it works before enabling it.").</p> <p>Finally, there are three other minor typos in the code in your question:</p> <ul> <li>You are missing an <code>#endif</code> at the end of nodo_colaypila.h</li> <li>in cola.h <code>nodo_colaypila&lt;T&gt;* ult, pri;</code> should be <code>nodo_colaypila&lt;T&gt; *ult, *pri;</code> - both are pointers.</li> <li>nodo_colaypila.cpp: The default parameter should be in the header file <code>nodo_colaypila.h</code>, not in this implementation file.</li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload