<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[undefined reference bei Funktions-Templates und aktivierter Optimierung]]></title><description><![CDATA[<p>Gegeben sei folgendes Minimalbeispiel:</p>
<p>class1.h</p>
<pre><code>#ifndef CLASS1_H
#define CLASS1_H
#include &lt;iostream&gt;

class Class1
{
public:
  template&lt;typename T&gt;
  void doSomething(const T&amp; param);
};

#endif // CLASS1_H
</code></pre>
<p>class1.cpp</p>
<pre><code>#include &quot;class1.h&quot;

template&lt;typename T&gt;
void Class1::doSomething(const T&amp; param)
{
  std::cout &lt;&lt; param &lt;&lt; std::endl;
}

void functionForExplicitInstantiation()
{
  int i;
  Class1 c;
  c.doSomething(i);
}
</code></pre>
<p>main.cpp</p>
<pre><code>#include &quot;class1.h&quot;

int main(int argc, char *argv[])
{
  int i = 5;
  Class1 a;
  a.doSomething(i);
  return 0;
}
</code></pre>
<p>Aus diesem Code kann ich problemlos ein funktionierendes Executeable erstellen mit dem Befehl<br />
<em>g++ class1.cpp main.cpp</em></p>
<p>Sobald ich g++ jedoch sage, dass er/sie/es optimieren soll, gibt es einen Linkerfehler:<br />
<em>g++ -O2 class1.cpp main.cpp<br />
/tmp/ccfPqCHd.o: In function <code>main': main.cpp:(.text.startup+0x17): undefined reference to</code>void Class1::doSomething&lt;int&gt;(int const&amp;)'</em></p>
<p>Im Prinzip ist mir klar, was hier passiert: Der Compiler kompiliert jede cpp-Datei einzeln und wirft dabei raus, was unnötig erscheint. In diesem Fall <em>Class1::doSomething&lt;int&gt;()</em>. Im Anschluss findet der Linker die Funktion nicht mehr in den Objektdateien und es kommt zu besagtem Fehler.</p>
<p>Mir ist aber nicht klar, <strong>warum</strong> das passiert. Mit <em>-O2</em> möchte ich dem Compiler sagen, er soll den gegebenen Code so kompilieren, dass dieser so schnell wie möglich ausgeführt werden kann. Ich sage <strong>nicht</strong>, dass irgendwelche Funktionen unnötig sind. Zwar ist ein kleines Executeable auch ganz nett, aber darum kann sich der Linker kümmern. Nach meinem Verständnis ist es Aufgabe des Linkers, allen benötigten Code (und nur den, denn ich will hier keine Library erstellen) aus den .o-Dateien zusammenzutragen und daraus ein Executeable zu machen.</p>
<p>Warum verhält sich der Compiler dennoch so &quot;besserwisserisch&quot;? Gibt es einen Weg, das abzustellen ohne die Optimierung zu opfern? Vielen Dank schonmal für Antworten!</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/335822/undefined-reference-bei-funktions-templates-und-aktivierter-optimierung</link><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Apr 2026 03:58:53 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/335822.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 13 Dec 2015 18:36:54 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to undefined reference bei Funktions-Templates und aktivierter Optimierung on Sun, 13 Dec 2015 18:36:54 GMT]]></title><description><![CDATA[<p>Gegeben sei folgendes Minimalbeispiel:</p>
<p>class1.h</p>
<pre><code>#ifndef CLASS1_H
#define CLASS1_H
#include &lt;iostream&gt;

class Class1
{
public:
  template&lt;typename T&gt;
  void doSomething(const T&amp; param);
};

#endif // CLASS1_H
</code></pre>
<p>class1.cpp</p>
<pre><code>#include &quot;class1.h&quot;

template&lt;typename T&gt;
void Class1::doSomething(const T&amp; param)
{
  std::cout &lt;&lt; param &lt;&lt; std::endl;
}

void functionForExplicitInstantiation()
{
  int i;
  Class1 c;
  c.doSomething(i);
}
</code></pre>
<p>main.cpp</p>
<pre><code>#include &quot;class1.h&quot;

int main(int argc, char *argv[])
{
  int i = 5;
  Class1 a;
  a.doSomething(i);
  return 0;
}
</code></pre>
<p>Aus diesem Code kann ich problemlos ein funktionierendes Executeable erstellen mit dem Befehl<br />
<em>g++ class1.cpp main.cpp</em></p>
<p>Sobald ich g++ jedoch sage, dass er/sie/es optimieren soll, gibt es einen Linkerfehler:<br />
<em>g++ -O2 class1.cpp main.cpp<br />
/tmp/ccfPqCHd.o: In function <code>main': main.cpp:(.text.startup+0x17): undefined reference to</code>void Class1::doSomething&lt;int&gt;(int const&amp;)'</em></p>
<p>Im Prinzip ist mir klar, was hier passiert: Der Compiler kompiliert jede cpp-Datei einzeln und wirft dabei raus, was unnötig erscheint. In diesem Fall <em>Class1::doSomething&lt;int&gt;()</em>. Im Anschluss findet der Linker die Funktion nicht mehr in den Objektdateien und es kommt zu besagtem Fehler.</p>
<p>Mir ist aber nicht klar, <strong>warum</strong> das passiert. Mit <em>-O2</em> möchte ich dem Compiler sagen, er soll den gegebenen Code so kompilieren, dass dieser so schnell wie möglich ausgeführt werden kann. Ich sage <strong>nicht</strong>, dass irgendwelche Funktionen unnötig sind. Zwar ist ein kleines Executeable auch ganz nett, aber darum kann sich der Linker kümmern. Nach meinem Verständnis ist es Aufgabe des Linkers, allen benötigten Code (und nur den, denn ich will hier keine Library erstellen) aus den .o-Dateien zusammenzutragen und daraus ein Executeable zu machen.</p>
<p>Warum verhält sich der Compiler dennoch so &quot;besserwisserisch&quot;? Gibt es einen Weg, das abzustellen ohne die Optimierung zu opfern? Vielen Dank schonmal für Antworten!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2479380</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2479380</guid><dc:creator><![CDATA[Mr Train]]></dc:creator><pubDate>Sun, 13 Dec 2015 18:36:54 GMT</pubDate></item><item><title><![CDATA[Reply to undefined reference bei Funktions-Templates und aktivierter Optimierung on Sun, 13 Dec 2015 19:22:13 GMT]]></title><description><![CDATA[<p>Das Problem ist ein ganz anderes: Templatedefinitionen müssen bei Instanzierung verfügbar sein. Das heißt, die Funktionsdefinition muss in den Header. Keine Angst, bei Templates darf man auch mehrfache Definitionen im Programm haben, sofern diese gleich sind.</p>
<p>Das wahre Wunder ist, dass der GCC offenbar in der Lage ist, die Definition auch über mehrere Dateien hinweg zu finden. Interessantes Feature, da muss ich mal tiefer graben, was es damit auf sich hat. Das <em>darf</em> er so machen, aber laut Sprachstandard muss dies nicht unterstützt werden. Und offenbar wird es nicht bei allen Compilereinstellungen unterstützt.</p>
<p>PS: Die Option, die für den Linker&quot;fehler&quot; sorgt ist <code>-finline-small-functions</code> . Ich könnte jetzt spekulieren, warum das so ist, aber letztlich ist das müßig, da Templatedefinitionen, wie gesagt, sowieso bei Instanzierung vorliegen müssen und es dann auch funktioniert, egal mit welcher Optimierungsstufe.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2479386</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2479386</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Sun, 13 Dec 2015 19:22:13 GMT</pubDate></item><item><title><![CDATA[Reply to undefined reference bei Funktions-Templates und aktivierter Optimierung on Sun, 13 Dec 2015 19:26:23 GMT]]></title><description><![CDATA[<p>Nur der Vollständigkeit halber: Man kann auch explizit Funktions Templates und Klassen instanzieren, ohne so eine Hilfsfunktion wo der Compiler eventuell Zeug wegoptimiert. Wenn du deine <code>functionForExplicitInstantiation</code> Funktion weglässt und stattdessen</p>
<pre><code>template void Class1::doSomething(const int&amp; param);
</code></pre>
<p>in die class1.cpp schreibst sollte es bei allen Optimierungsstufen funktionieren. Aber da Templates eigentlich in den Header gehören damit die Funktion auch nicht nur für <code>int</code> sondern alle Typen funktionieren soll ist sowas sehr unüblich.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2479390</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2479390</guid><dc:creator><![CDATA[sebi707]]></dc:creator><pubDate>Sun, 13 Dec 2015 19:26:23 GMT</pubDate></item><item><title><![CDATA[Reply to undefined reference bei Funktions-Templates und aktivierter Optimierung on Sun, 13 Dec 2015 20:00:09 GMT]]></title><description><![CDATA[<p>Danke für die schnellen Antworten. Die Erklärung, dass <em>doSomething&lt;int&gt;()</em> ge-inline-t wird und die Methode daher nicht mehr gefunden wird, ergibt für mich Sinn.</p>
<p>SeppJ schrieb:</p>
<blockquote>
<p>Das wahre Wunder ist, dass der GCC offenbar in der Lage ist, die Definition auch über mehrere Dateien hinweg zu finden.</p>
</blockquote>
<p>Finde ich ehrlich gesagt nicht so verwunderlich. Template hin oder her, es gibt einen gemeinsamen Header mit einer Deklaration. Der Name der Funktion ist in beiden cpp-Dateien eindeutig bestimmbar, nämlich <em>Class1::doSomething&lt;int&gt;()</em>.</p>
<p>Mit dem Tipp von sebi707 klappt es nun. Ist das nun ein g++-spezifischer Hack oder entspricht das dem C++-Standard?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2479396</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2479396</guid><dc:creator><![CDATA[Mr Train]]></dc:creator><pubDate>Sun, 13 Dec 2015 20:00:09 GMT</pubDate></item><item><title><![CDATA[Reply to undefined reference bei Funktions-Templates und aktivierter Optimierung on Sun, 13 Dec 2015 20:08:00 GMT]]></title><description><![CDATA[<p>Mr Train schrieb:</p>
<blockquote>
<p>Mit dem Tipp von sebi707 klappt es nun. Ist das nun ein g++-spezifischer Hack oder entspricht das dem C++-Standard?</p>
</blockquote>
<p>Das entspricht dem C++ Standard. Allerdings fallen mir kaum Gründe ein warum man dies tun sollte. Warum die Funktion nicht einfach mit <code>const int&amp;</code> als Parameter deklarieren, wenn es die eh nur für <code>int</code> geben soll?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2479399</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2479399</guid><dc:creator><![CDATA[sebi707]]></dc:creator><pubDate>Sun, 13 Dec 2015 20:08:00 GMT</pubDate></item><item><title><![CDATA[Reply to undefined reference bei Funktions-Templates und aktivierter Optimierung on Sun, 13 Dec 2015 20:16:07 GMT]]></title><description><![CDATA[<p>Mr Train schrieb:</p>
<blockquote>
<p>SeppJ schrieb:</p>
<blockquote>
<p>Das wahre Wunder ist, dass der GCC offenbar in der Lage ist, die Definition auch über mehrere Dateien hinweg zu finden.</p>
</blockquote>
<p>Finde ich ehrlich gesagt nicht so verwunderlich. Template hin oder her, es gibt einen gemeinsamen Header mit einer Deklaration. Der Name der Funktion ist in beiden cpp-Dateien eindeutig bestimmbar, nämlich <em>Class1::doSomething&lt;int&gt;()</em>.</p>
</blockquote>
<p>Stimmt, irgendwie bin ich selber durcheinander gekommen, welche Funktion wo aufgerufen wird. So macht das mit dem inline Sinn und es macht auch Sinn, warum die Funktion gefunden wird.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2479401</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2479401</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Sun, 13 Dec 2015 20:16:07 GMT</pubDate></item><item><title><![CDATA[Reply to undefined reference bei Funktions-Templates und aktivierter Optimierung on Sun, 13 Dec 2015 20:47:29 GMT]]></title><description><![CDATA[<p>sebi707 schrieb:</p>
<blockquote>
<p>Allerdings fallen mir kaum Gründe ein warum man dies tun sollte. Warum die Funktion nicht einfach mit <code>const int&amp;</code> als Parameter deklarieren, wenn es die eh nur für <code>int</code> geben soll?</p>
</blockquote>
<p>Der oben gepostete Code ist ein Minimalbeispiel, dessen einziger Zweck es ist, die selbe Fehlermeldung zu reproduzieren, die ich in einem realen Projekt bekomme. Ich kann hier ja nicht tausende Zeilen Code posten (und will den Code auch nicht preisgeben).</p>
<p>Im realen Code gibt es natürlich auch noch weitere Template-Instanzen von <code>Class1::doSomething()</code> . Außerdem wird dort <em>main.cpp</em> oft geändert, <em>class1.cpp</em> jedoch selten. Durch die explizite Instantiierung in der <em>class1.cpp</em> Datei erhalte ich eine kürzere Compilezeit, als wenn ich die Methodendefinition mit in den Header stecken würde.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2479404</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2479404</guid><dc:creator><![CDATA[Mr Train]]></dc:creator><pubDate>Sun, 13 Dec 2015 20:47:29 GMT</pubDate></item></channel></rss>