2017-02-15 8 views
4

Ich habe eine alte C++ - DLL ausgegraben, und ich möchte es in einem meiner Projekte, in VS2015.Ausgabe der void pointer Funktion

Das Problem ist, es kompiliert nicht. Ich habe mich mit einem Typen im Team in Verbindung gesetzt, der den Code überhaupt erstellt hat, und er ist überzeugt, dass genau der gleiche Code mit VS2010 kompiliert wurde.

Ich habe einen Fehler in einer ansonsten sehr einfachen Funktion:

Ausschnitt des Kopfes:

/* 
Data input 
*/ 
istream* input; //Source of data 
long inputpos; // Current position in the data stream 

Und der Code selbst:

// Helper function to increment a counter while reading a character 
void* Calculator::inputstream_get(char& ch) 
{ 
    ++inputpos; 
    return input->get(ch); 
} 

Am Ende bekomme ich einen Fehler C2440:

'return': cannot convert from 'std::basic_istream<char,std::char_traits<char>>' to 'void *' 

Es ist mein Verständnis (ich bin kein C++ - Experte, den ich sagen muss ...), dass void pointers jede Art von Daten darstellen könnte, irre ich mich?

Gibt es eine Möglichkeit, meinen istream in einen void pointer zu "werfen"?

Vielen Dank für Ihre Hilfe

+0

'void *' kann jeden Typ von Zeiger darstellen, nicht nur irgendeinen Typ von Punkt. 'std :: basic_istream >' ist kein Zeigertyp und kann daher nicht in 'void *' umgewandelt werden. Ein 'std :: basic_istream > *' könnte jedoch sein. – Kevin

+0

_Ich habe mich mit einem Mann im Team in Verbindung gesetzt, der den Code erstellt hat, und er ist überzeugt, dass genau der gleiche Code mit VS2010 kompiliert wurde. _ Die Aussage deines Typen ist korrekt - ** ** kompiliert mit VS2010. –

+0

Ich bekomme von all Ihren Kommentaren, dass dies nicht "richtiger" Code ist (was VS2015 betrifft). Warum hat es mit VS2010 kompiliert? Hat sich der Standard geändert? Vielen Dank für Ihre Hilfe – Maxime

Antwort

6

umwandeln. Der Grund, warum dies in VS 2010 (C++ 03) und nicht in VS 2015 (C++ 11) kompiliert, ist, dass in C++ 03, Standard-Bibliotheksströme definierten eine implizite Umwandlung zu void*; Der Zweck dieser Konvertierung bestand darin, das Testen auf Wahrhaftigkeit zuzulassen (wie while (cin >> x)), ohne eine implizite Umwandlung in bool zu erlauben (was es erlauben würde, solche Monstrositäten wie 1 + (cin >> x) zu kompilieren).

beachten, dass der Wert der zurück void* underspecified wurde: es war entweder ein Null-Zeiger, wenn der Strom in einem ausgefallenen Zustand ist, oder ein unbestimmter Nicht-Null-Zeiger, wenn die in einem guten Zustand des stram.

C++ 11 eingeführt, um den Begriff der expliziten Umwandlungsoperatoren und kontextuelle Umwandlung zu bool, was bedeutet, dass diese „hacky“ Conversions void* durch eine sichere explicit operator bool() const im Standard ersetzt wurden. Dies führt natürlich dazu, dass der Code nicht als C++ 11 kompiliert werden kann.

Wie Sie dieses Problem lösen können, ist Calculator::inputstream_get wie folgt ändern:

void* Calculator::inputstream_get(char& ch) 
{ 
    ++inputpos; 
    return input->get(ch) ? this : nullptr; 
} 

Dies bewahrt die Semantik der einen Null-Zeiger auf Versagen der Rückkehr und eine unbestimmte Nicht-Null-Zeiger auf Erfolg.

+1

Beachten Sie, dass die vorgeschlagene Lösung abwärtskompatibel zu C++ 03/VS2010 ist. – MSalters

0

Um Ihre letzte Frage zu beantworten. Sie können keinen Nichtzeiger auf einen Zeiger anwenden. Aber Sie können jeden Zeiger auf einen void-Zeiger mit (void *)

+0

Sie brauchen die Umwandlung nicht, wenn Sie _to_ in einen void-Zeiger konvertieren, nur wenn Sie _from_ eins konvertieren. –

0

Dies ist der Deal. http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool

In C++ 03 war das Operator void * und in C++ 11 ist das Operator Bool.

Ändern Sie diese void * zu bool. Beachten Sie, dass der Code nach der Änderung in C++ 03-Compiler nicht verwendbar sein wird.Sie können es in einer tragbaren Weise mit

lösen
if (input->get(ch)) return true; 
else return false; 

Eigentlich ist der beste Weg, Verweis auf das tatsächliche istream-Objekt zurückzugeben.