2017-07-21 1 views
0

Ich versuche, eine ArrayList-Klasse in C++ als Lernerfahrung zu machen. Ähnlich wie die Java ArrayList-Klasse ist es ein dynamisches Array, das interne Array heißt 'content'. Anders als in Java wollte ich, dass meine ArrayList Zeiger und Nicht-Zeiger aufnehmen kann. Aber ich bekomme ein Problem, ich verwende std :: is_pointer :: value, um zu überprüfen, ob der generische Typ ein Zeiger innerhalb einer Reihe von Funktionen ist. Wenn es sich um einen Zeiger handelt, muss die Funktion anders aussehen, als wenn es kein Zeiger wäre. Mein Beispiel unten zeigt meine Funktion printAll(), die jedes Element in dem Array in separaten Zeilen drucken soll. Wenn der generische Typ ein Zeiger ist, muss die Methode jedes Element im Array vor der Ausgabe dereferenzieren.Deaktivieren Sie Compiler-Warnung 2100 für generische Methode in einer List-Klasse, die möglicherweise Zeiger enthalten oder nicht

int main() { 
     ArrayList<int> a = ArrayList<int>(); 
     a.add(1); 
     a.add(2); 
     a.add(3); 
     a.printAll(); 
     cin.ignore(); 
    } 

    #pragma warning(push) 
    #pragma warning(disable : 2100) 
    template<class T> 
    void ArrayList<T>::printAll() { 
     if (std::is_pointer<T>::value) { 
      for (int i = 0; i < this->occupiedSize; i++) { 
       cout << "[" << i << "] " << *this->content[i]; 
       cout << endl; 
      } 
     } else { 
      for (int i = 0; i < this->occupiedSize; i++) { 
       cout << "[" << i << "] " << this->content[i]; 
       cout << endl; 
      } 
     } 
    } 
    #pragma warning(pop) 

Auf der Linie: cout << "[" << i << "] " << *this->content[i]; Ich bin immer Warnungen: C2100: illegal indirection und C2088: '< <': illegal für Klasse

Ich gehe davon aus das ist, weil die Liste ist nicht von einem Zeigertyp und kann daher nicht mit * dereferenziert werden. Aber in einer Nicht-Zeiger-Liste sollte std :: is_pointer :: value den Wert false zurückgeben und der Code in diesem Block wird niemals ausgeführt, daher sollte es kein Problem sein. Das Deaktivieren der Warnung scheint nicht zu helfen.

Wenn ich tun:

int main() { 
    ArrayList<int*> a = ArrayList<int*>(); 
    a.add(new int(1)); 
    a.add(new int(2)); 
    a.add(new int(3)); 
    a.printAll(); 
    cin.ignore(); 
} 

Es total gut funktioniert. Irgendwelche Ideen wie ich dieses Problem lösen kann oder wie ich diese Funktionalität besser umsetzen kann?

Ich benutze Windows 10, Microsoft Visual Studio (neueste Version glaube ich).

+1

"Deaktivierung der Warnung scheint nicht zu helfen" - gut duh! Natürlich hilft es nicht, es zu deaktivieren - das bringt den Compiler einfach zum Schweigen, es ändert nichts. Ihr Code ist genauso kaputt, jetzt sagt Ihnen der Compiler nichts mehr. –

+0

Ich bekomme das, aber wie kann ich es reparieren? Was ist der Weg dazu? –

+0

Machen Sie, was die C++ - Bibliothek tut, und lassen Sie den Druck dem Benutzer überlassen. – molbdnilo

Antwort

2

Dieses Problem hier ist, dass, obwohl Sie nie

if (std::is_pointer<T>::value) { 
    for (int i = 0; i < this->occupiedSize; i++) { 
     cout << "[" << i << "] " << *this->content[i]; 
     cout << endl; 
    } 
} 

Wenn T der Compiler einen nicht Zeigertyp kompilieren immer noch, dass Code-Block ist eintreten würde. Da es eine ungültige Syntax hat, erhalten Sie eine Compiler-Warnung.

In der kommenden C++ 17 können Sie constexpr if verwenden, die den Code aus der Kompilierung entfernen, wenn die Bedingung nicht erfüllt ist.

Wenn Sie keinen Zugriff auf einen Compiler haben, der diese Funktion unterstützt, müssen Sie verwenden und zwei Überladungen der Funktion haben. Eine für if T ist ein Zeigertyp und einer für, wenn T kein Zeigertyp ist. Das würde aussehen wie

template<class T, std::enable_if_t<typename std::is_pointer<T>::value>* = nullptr> 
void ArrayList<T>::printAll() { 
    for (int i = 0; i < this->occupiedSize; i++) { 
     cout << "[" << i << "] " << *this->content[i]; 
     cout << endl; 
    } 
} 

template<class T, std::enable_if_t<typename !std::is_pointer<T>::value>* = nullptr> 
void ArrayList<T>::printAll() { 
    for (int i = 0; i < this->occupiedSize; i++) { 
     cout << "[" << i << "] " << this->content[i]; 
     cout << endl; 
    } 
} 
+0

Das funktioniert aber nur, wenn ich die Funktion innerhalb der Header-Datei definiere. Wenn ich die Funktion in der cpp-Datei definiere, heißt es: Die Funktionsdefinition kann keiner vorhandenen Deklaration zugeordnet werden. Irgendwelche Ideen? –

+0

@OllieKampo Sie können Vorlagenfunktionen in einer cpp-Datei nicht definieren. siehe [dies] (https://stackoverflow.com/questions/495021/why-can-templates-only-be-implementiert-in-the-header-file) – NathanOliver

+0

Ok, vielen Dank für Ihre Hilfe! Sehr nette Antworten :) –

Verwandte Themen