2016-05-07 8 views
-2

Der Code unten (-std = C++ 11) nach einer "naiven" Ansicht sollte funktionieren. Stattdessen ist es nicht (sollte bekannt sein und warum es nicht verstanden wird). Welcher ist der kürzeste Weg, den Code zu modifizieren (& zu überladen), damit er sich entsprechend der "naiven" Ansicht verhält? Sollte das nicht als Option während der Erstellung von stl-Objekten angegeben werden (ohne zu viel zu schreiben)?Wie man idempotent einen Verweis auf eine Dereferenzierung eines Iterators macht

#include <iostream> 
#include <vector> 

int main(int argc, char **argv) 
{ std::vector<int> A{10,20,30}; 
    auto i=A.begin(); 
    auto j=&*i; 
    std::cout<<"i==j gives "<<(i==j)<<std::endl; 
    return 0; 
} 
+1

Das sieht für mich wie ein [XY Problem] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) aus. Was ist dein eigentliches Ziel? An welchem ​​Punkt möchten Sie, dass dieses Verhalten gültig ist? – Pixelchemist

+0

Ja. * Warum * möchten Sie den Operator "In tatsächliche Adresse konvertieren" (& *) unterbrechen? –

+0

erklären, was Sie „Arbeit“ –

Antwort

0

Zunächst, im Code-Schnipsel i abzieht zu std::vector<int>::iterator und j abzieht zu int*. Der Compiler kann nicht std::vector<int>::iterator gegen int* vergleichen.

Dazu heraus zu arbeiten, könnten Sie eine überladene operator== liefern, die Vektor-Iteratoren gegen Vektorwert Typ Zeiger auf die folgende Weise vergleichen würde:

template<typename T> 
bool operator==(typename std::vector<T>::iterator it, T *i) { 
    return &(*it) == i; 
} 

template<typename T> 
bool operator==(T *i, typename std::vector<T>::iterator it) { 
    return it == i; 
} 

Live Demo

+0

Dies vergleicht die Adressen des Elements für die Gleichheit und nicht das Element selbst. ich lieh mir Ihre Idee unter, aber dereferenziert den Zeiger und Iterator. Hoffnung, die ok Etikette ist. – T33C

+0

@ T33C vielleicht OP will Adressen vergleichen, anstatt Werte, (dies ist anders, wenn Vektor mehrere Kopien des gleichen Wert enthält) –

+0

Vielleicht ... aber seltsames Ding, besonders mit einem Behälter zu tun, der seine Elemente verschieben könnte, wenn mehr hinzugefügt werden und es Größe ändern muss – T33C

0

Dies sollte nicht funktionieren - nicht sogar "nach einer" naiven "Ansicht". Obwohl jeder Zeiger ein Iterator ist, ist das Gegenteil nicht unbedingt wahr. Warum würden Sie erwarten, dass das funktioniert?

Es würde unter zwei Szenarien funktionieren:

  1. Die iterator der std::vector<T> Implementierung ist eigentlich ein T*. Dann würde Ihr Code seit decltype(i) == int* und decltype(j) == int*) funktionieren. Dies mag für einige Compiler der Fall sein, aber Sie sollten sich nicht einmal darauf verlassen, wenn es für Ihren Compiler wahr ist.

  2. Der Dereferenzierungsoperator nicht ein Objekt vom Typ T zurück, sondern eher etwas, das T konvertierbar ist und hat eine überladenes operator&, die wieder den Iterator gibt. Dies ist aus sehr guten Gründen nicht der Fall.

könnten Sie -wie andere haben suggested- Überlastung operator== zu prüfen, ob beide Indirekt (Zeiger und Iterator) das gleiche Objekt verweisen aber ich vermute, dass Sie die Adresse des Operators wollen Sie wieder den Iterator zu geben, die nicht sein kann erreicht, wenn der Iterator kein Zeiger ist, weil der Objekttyp, der in dem Vektor gespeichert ist, keine Vorstellung von Vektor/Iterator oder was auch immer hat.

Das Problem ist nicht in der Gleichheits-Operator, was ich brauche, ist die Dereferenzierungsoperator definieren einen Iterator

Sie können nicht zu geben. Der betreffende Dereferenzierungsoperator ist std::vector<int>::iterator, der Teil der Standardbibliothek ist, und Sie können ihn manipulieren (und nicht).


anzumerken, dass, da C++ 11 in einer std::vector<T, A>,

  • value_type ist T und
  • referenceT& ist.

Darüber hinaus gilt Folgendes:

  • All Eingang Iteratoreni Unterstützung *i, die einen Wert vom Typ gibt T etwas den Werttyp diesen Iterator.
  • Der Iterator std::vector<T> muss T als seinen Werttyp haben.
  • Ein Iterator von std::vector<T> ist ein Eingabe-Iterator.
+0

Die Schablone std :: vector hat viele Argumente neben dem ersten. Diese sind verfügbar, um zu sein Also suche ich nach einer Lösung, die das gewünschte Verhalten geben kann .. –

+0

@GeorgeKourtis: Wie ich unter Ihrer Frage gefragt habe stion: Warum willst du das machen? ... Ein 'std: vector' Template Argument ist nur der Elementtyp, der andere ist über die Zuweisung. Der zweite beeinflusst nicht das Verhalten, das Sie ändern möchten. Sie könnten das Problem umgehen, indem Sie Ihren tatsächlichen Typ in einen Typ einschließen, der einen Zeiger auf den Vektor speichert, in dem er gespeichert ist. Sobald er initialisiert ist, verwendet er 'operator & ', um Ihnen den richtigen Iterator zu geben, aber das wäre nicht sehr nützlich. – Pixelchemist

+0

Das Mitglied, das über die Zuweisung ist, gibt eine Menge Dinge wie value_type, pointer, reference, ich nehme an, mit dem ist möglich, das Ergebnis zu erhalten. –

1

Das Problem kann nicht gelöst werden. Es gibt drei Gründe, es kann nicht gelöst werden.

Erstes Problem

Die operator & Sie überlasten müssen, ist die operator & für den Elementtyp des Vektors. Sie können operator & nicht für beliebige Typen überladen, insbesondere können Sie sie nicht für eingebaute Typen überladen (wie int in Ihrem Beispiel).

Zweites Problem

Vermutlich Sie dies für std::vector arbeiten möchten, std::array und Einbau-Arrays? Auch wahrscheinlich std::list, std::deque, etc? Du kannst nicht. Die Iteratoren für jede dieser enthält unterschiedlich sein (in der Praxis. In Theorie, einige von ihnen Iteratoren teilen konnte, aber ich bin nicht bekannt, dass Standard-Bibliothek, wo sie tun)

Drittes Problem

Wenn Sie bereit sind zu akzeptieren, dass dies nur für std::vector<MyType> funktionieren würde, dann könnte man MyType::operator & überlasten - aber man konnte immer noch nicht herausfinden, welche std::vector<MyType> die MyType Objekt lebt in (und Sie müssen, dass der Iterator zu erhalten).

+0

In Bezug auf das erste Problem ist der Ansatz nicht genau. Was überladen werden sollte, ist der Operator & für eine Referenz auf int (es ist wichtig, eine Referenz zu sein, denn wenn es nicht offensichtlich ist, können wir den Iterator nicht erhalten). In Bezug auf die Überladung von & für eingebaute Typen nehme ich an, dass Sie richtig sind, also sollte das Problem modifiziert werden, anstatt int eine Struktur zu haben, um es tun zu können. –

+0

In Bezug auf das zweite Problem kann eine Referenz auf ein Objekt einfach in einen Iterator für einen Random-Access-Container konvertiert werden. Für einen nicht-wahlfreien Zugriff ist die Operation langsam. –

+0

In Bezug auf das dritte Problem sind Sie richtig. Wir können einen Verweis auf einen Iterator nur dann konvertieren, wenn beide Referenzen und Iteratoren als Zeiger implementiert sind. Dies ist auf der anderen Seite in üblichen Implementierungen der Fall. –