2016-04-12 24 views
0

ich einige statische Funktionen in ihren eigenen .h und CPP-Dateien definiert haben, so können diese von anderswo ohne Notwendigkeit Instanziierung genannt werden:C++ const Member-Funktionen, nicht-Typ-Vorlagen und externe Symbole

functions.h

#pragma once 
class functions { 
public: 
    static const int addition(const int&, const int&); 
    static const int product(const int&, const int&); 
}; 

functions.cpp

#include "functions.h" 
const int functions::addition(const int& op1, const int& op2) { 
    return op1 + op2; 
} 
const int functions::product(const int& op1, const int& op2) { 
    return op1 * op2; 
} 

ich habe auch einen Abschnitt für die Programmeinstellungen erstellt, wo ich welche der Funktionen definieren wählen:

constants.h

#pragma once 
const int modulus = 10; 
extern const int(*operation)(const int&, const int&); 

constants.cpp

#include "constants.h" 
#include "functions.h" 
const int(*operation)(const int&, const int&) = &functions::addition; 

Dieser Code funktioniert wie erwartet mit dem folgenden Beispiel:

main.cpp

#include <iostream> 
#include "constants.h" 
int main() { 
    int a = 7, b = 4; 
    std::cout << operation(a,b) % modulus << std::endl; 
} 

Problem ist, jetzt möchte ich das fu parametrisieren nktionen hinaus und Produkt einer nicht-Typ-Vorlage verwenden, wie zum Beispiel:

functions.h

#pragma once 
class functions { 
public: 
    template<const int&> static const int addition(const int&, const int&); 
}; 

functions.cpp

#include "functions.h" 
template<const int& sub> const int functions::addition(const int& op1, const int& op2) { 
    return op1 + op2 - sub; 
} 

Der spätere Code bricht, egal wie ich versuche, anzupassen die anderen Dateien. Ich habe alles getan, was ich mir vernünftig (und sinnlos) vorstellen konnte.

Jede Hilfe zum Umschreiben des Codes auf Konstanten. * Wird sehr geschätzt.

+0

Seitennotiz: Sie brauchen nicht diese erste Klasse. Wenn Sie einen separaten Namespace für Ihre Funktionen benötigen, verwenden Sie einen Namespace. – molbdnilo

+0

Vielen Dank für Ihren Rat, aber die Klasse gruppiert andere Funktionen, die sich mit den gegebenen Funktionen befassen. Da sie in dem Problem keine Rolle spielten, entschied ich mich, sie vom minimalen Beispiel auszuschließen. – jvier

+0

Ich sehe nicht, wie das ausgeht. Eine Klasse, die nur statische Member hat, ist eher eine Java-/C#/Smalltalk-Sache. – molbdnilo

Antwort

0

Vorlagen werden zur Kompilierzeit instanziiert, und dafür muss die Definition bekannt sein - Sie müssen die Vorlagendefinition in der Kopfzeile haben.

Auch wenn Sie das tun, haben Sie keine int als Parameter, sondern eine const int&.
Das bedeutet, dass Sie es mit einem Lvalue instanziieren müssen, dessen Identität (d. H. Ort) zur Kompilierungszeit bestimmt werden kann.
Das bedeutet wiederum, dass der Parameter eine Variable mit externer Verknüpfung sein muss - keine temporäre oder lokale Variable.

Mit anderen Worten:

extern int x; 

void foo() 
{ 
    addition<1>(2,3); // Not good; not an lvalue 
    const int y = 1; 
    addition<y>(2,3); // Not good; no linkage 
    addition<x>(2,3); // Good 
} 

Sie wollen wahrscheinlich template<int sub> stattdessen verwenden.

(Eine andere Seite. Hinweis: const Verweise auf primitive Typen sind sinnlos Alles, was sie tun, ist Overhead hinzufügen.)

+0

Vielen Dank! Ich denke, jetzt ist es an mir, zu entscheiden, wo die Variable x definiert werden soll. Was das Übergeben von Verweisen auf primitive Typen betrifft, so ist dies sicherlich nicht der Fall meines ursprünglichen Codes. Hinzugefügt: Ich erwäge, neu zu definieren, aber ich kann mich erinnern, dass andere Fehler verursachen. Prost. – jvier

+0

Die Verwendung der Vorlage kompiliert immer noch nicht aus demselben Grund, ungelöstes externes Symbol. – jvier

+0

@jvier Hast du die Definition in die Kopfzeile geschrieben? (Siehe [hier] (http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file).) – molbdnilo

0

Template Definitionen sollten entweder an den Compiler während der Instanziierung oder explizit instanziiert sichtbar sein. Da ich sehr bezweifle, dass Sie alle möglichen Versionen von Integer-Templates explizit instanziieren können, haben Sie die Definitons in den Header eingefügt.

Dann kommt das Problem von operations. Da es sich um einen Funktionszeiger handelt, kann er nur auf spezifische Instanz Ihrer Vorlage verweisen - die Instanz, die mit einer bestimmten Integer-Vorlage instanziiert wurde. Zweifel, dass es überhaupt verwendbar ist.

Ich schlage vor, Ihr Design zu überdenken.

+0

Danke! Ich überarbeite ständig mein Design, aber es wäre eine gute Idee, Operationen als eine Instanz der Funktionsvorlage zu definieren. Was auch immer ich getan habe, warf beim Kompilieren externe Linkprobleme auf. – jvier

+0

Ich nehme eine tiefere Lektüre von dir Kommentar und es ist aufschlussreich. Also, ich denke, explizite Instanziierung muss eines dieser Beispiele mit rekursiven Templates sein ("variadic", wenn mein Wissen in Ordnung ist). Vielen Dank! – jvier