2017-01-16 6 views
0

mit dem folgenden CodeProbleme mit emplace_back und bewegen Zuordnung Konstrukteurs

test.h:

#ifndef __graph_aufbau_header__ 
#define __graph_aufbau_header__ 
#include <vector> 
#include <queue> 
#include <string> 

using namespace std; 

class Knoten { 
    public: 
     unsigned int nummer; 
     double x_1; 
     double x_2; 
     unsigned int abstand; 

     Knoten(unsigned int num, double x1, double x2) : nummer(num), x_1(x1), x_2(x2), abstand(-1) {}; 
     Knoten(Knoten&& anderer) : nummer(anderer.nummer), x_1(anderer.x_1), x_2(anderer.x_2), abstand(anderer.abstand) {}; 
     Knoten& operator=(Knoten&& anderer) = default; 
}; 

class Kante { 
    public: 
     unsigned int quellknotennum; 
     unsigned int zielknotennum; 
     unsigned int gewicht; 

     Kante(unsigned int qnum, unsigned int znum, unsigned int gew) 
     : quellknotennum(qnum), zielknotennum(znum), gewicht(gew) 
     {}; 

     Kante(Kante&& andere) 
     : quellknotennum(andere.quellknotennum), 
     zielknotennum(andere.zielknotennum), 
     gewicht(andere.gewicht) {}; 

     Kante& operator=(const Kante& andere) = default; 
     inline bool operator<(const Kante& kante_2){ 
      return this->quellknotennum < kante_2.quellknotennum; 
     }; 
}; 

class Offset { 
    public: 
     unsigned int knoten_num; 
     unsigned int kanten_num; 

     Offset(unsigned int knnum, unsigned int kanum) 
     : knoten_num(knnum), kanten_num(kanum) 
     {}; 
     Offset(Offset&& anderer) 
     : knoten_num(anderer.knoten_num), kanten_num(anderer.kanten_num) {}; 

     Offset& operator=(Offset& anderer) = default; 
}; 

class Graph { 
    public: 
      vector<Knoten> coordList; 
      vector<Kante> edgeList; 
      vector<Offset> edgeOffsets; 
      //vector<unsigned int> abstand; 

      Graph() : coordList(), edgeList(), edgeOffsets(){}; 

      void knoten_einlesen(double x_1, double x_2); 
      void kante_einlesen(unsigned int quellknoten, unsigned int zielknoten, unsigned int gewicht); 
      void offset_einlesen(unsigned int nummer, unsigned int kante); 
      void einlesen(string quelle); 
      Knoten naechster_Nachbar(Knoten& knoten); 
}; 

#endif 

test.cc:

// kein iostream 
#include <fstream> // benötigt für die Deklaration eines Dateistroms 
#include <iostream> 
#include <string> 
#include <sstream> // zum Splitten 
//#include <regex> 
#include <cstdlib> // Zur Umwandlung von Strings in Doubles 
#include <algorithm> // fuer find_if() 
#include <queue> 
#include <vector> 
#include "test.h" 

using namespace std; 

void Graph::knoten_einlesen(double x_1, double x_2){ 
    unsigned int neue_position = coordList.size(); 
    coordList.emplace_back(neue_position, x_1, x_2); 
} 

void Graph::kante_einlesen(unsigned int knoten_1, unsigned int knoten_2, unsigned int gewicht){ 
    edgeList.emplace_back(knoten_1, knoten_2, gewicht); 
} 

void Graph::offset_einlesen(unsigned int nummer, unsigned int kante){ 
    edgeOffsets.emplace_back(nummer, kante); 
} 

void Graph::einlesen(string quelle){ 
    ifstream datendatei(quelle); 

    if (datendatei.is_open()){ 
     string aktuelle_zeile; 

     getline(datendatei, aktuelle_zeile); 
     unsigned int anzahl_knoten = stoi(aktuelle_zeile); 

     getline(datendatei, aktuelle_zeile); 
     unsigned int anzahl_kanten = stoi(aktuelle_zeile); 

     unsigned int nummer, position; 
     for(auto& knoten: coordList){ 
      nummer = knoten.nummer; 
      auto erste_kante = find_if(edgeList.begin(), edgeList.end(), [nummer] (Kante kante)\ 
      {return nummer == kante.quellknotennum;}); 
      position = erste_kante - edgeList.begin(); // Position der ersten Kante, die mit dem Knoten verbunden ist, in edgeOffsets 
      offset_einlesen(nummer, position); 
     } 


     datendatei.close(); 
    } 
} 

Knoten Graph::naechster_Nachbar(Knoten& knoten){ 
    return coordList.at(edgeList.at(edgeOffsets.at(knoten.nummer).kanten_num).zielknotennum); 
} 

, ich die folgende Fehlermeldung erhalten durch Rufen g++ -std=gnu++11 test.cc:

test.cc: In member function 'Knoten Graph::naechster_Nachbar(Knoten&)': 
test.cc:55:96: error: use of deleted function 'constexpr Knoten::Knoten(const Knoten&)' 
     return coordList.at(edgeList.at(edgeOffsets.at(knoten.nummer).kanten_num).zielknotennum); 
                           ^
In file included from test.cc:11:0: 
test.h:10:11: note: 'constexpr Knoten::Knoten(const Knoten&)' is implicitly declared as deleted because 'Knoten' declares a move constructor or move assignment operator 
    class Knoten { 
      ^~~~~~ 
In file included from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algobase.h:71:0, 
       from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/char_traits.h:39, 
       from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/ios:40, 
       from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/istream:38, 
       from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/fstream:38, 
       from test.cc:2: 
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Iter_pred<_Predicate>::operator()(_Iterator) [with _Iterator = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = Graph::einlesen(std::__cxx11::string)::<lambda(Kante)>]': 
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algo.h:120:14: required from '_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = __gnu_cxx::__ops::_Iter_pred<Graph::einlesen(std::__cxx11::string)::<lambda(Kante)> >]' 
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algo.h:161:23: required from '_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with _Iterator = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = __gnu_cxx::__ops::_Iter_pred<Graph::einlesen(std::__cxx11::string)::<lambda(Kante)> >]' 
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algo.h:3817:28: required from '_IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = Graph::einlesen(std::__cxx11::string)::<lambda(Kante)>]' 
test.cc:44:57: required from here 
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/predefined_ops.h:234:11: error: use of deleted function 'constexpr Kante::Kante(const Kante&)' 
    { return bool(_M_pred(*__it)); } 
      ^~~~~~~~~~~~~~~~~~~~ 
In file included from test.cc:11:0: 
test.h:22:11: note: 'constexpr Kante::Kante(const Kante&)' is implicitly declared as deleted because 'Kante' declares a move constructor or move assignment operator 
    class Kante { 
      ^~~~~ 
test.cc:43:99: note: initializing argument 1 of 'Graph::einlesen(std::__cxx11::string)::<lambda(Kante)>' 
       auto erste_kante = find_if(edgeList.begin(), edgeList.end(), [nummer] (Kante kante)\ 
                           ^

(Sie die Fehler nicht verpassen auf der rechten Seite gedruckt, versteckt Seite)

Ich habe viele Stunden versucht, dieses Problem und heute zu lösen, ich habe keine Ahnung, was hier schief geht. Anscheinend ruft der Code einen implizit gelöschten Move-Konstruktor der Klasse "Knoten" in der Methode naechster_nachbar (..) auf - aber ich weiß nicht, warum dies passiert und wie ich die entsprechende Fehlermeldung verhindern kann.

Der andere Teil (der große, leicht obskure) wird wahrscheinlich irgendwo in der Funktion einlesen (...) (Lambda-Funktion?), Vielleicht aus dem gleichen Grund wie der erste verursacht.

Der angegebene Code braucht nicht in der Lage sein Standalone zu kompilieren oder sogar vollständig und sinnvoll sein; Sein einziges Ziel ist es, die generierte Fehlermeldung zu demonstrieren. Ich konnte die Größe dieses minimalen Beispiels nicht weiter reduzieren. Wir sind gezwungen, C++ 11 zu verwenden (die Befehlszeilenoption ist also obligatorisch).

Vielen Dank im Voraus!

+4

'__graph_aufbau_header__' Kennung ist reserviert, da sie fortlaufende Unterstriche enthält. Sie sollten mit einem anderen Header Guard kommen. – user2079303

+0

Die Fehlermeldung sagt genau was falsch ist - etwas versucht, eine implizit gelöschte * Kopie * Ctor (nicht eine Bewegung Ctor, wie Sie schreiben) zu verwenden. Es wird implizit gelöscht, weil Sie einen move ctor, aber keinen copy ctor deklariert haben. Definieren Sie auch eine Kopie ctor und der Fehler wird weggehen (vorausgesetzt, eine Kopie ctor macht Sinn für Ihre Klasse). – Danra

Antwort

2

Sie haben Move-Konstruktoren für Knoten und Kante angegeben, dadurch werden Standard-Kopierkonstruktoren gelöscht. Wenn man einen eigenen Move-Konstruktor schreibt, dann wird angenommen, dass für diese Klasse eine nicht-triviale Logik erforderlich ist. Wenn diese Logik also für einen Move-Konstruktor/Zuweisungsoperator bereitgestellt wird, benötigen auch reguläre Versionen diese Logik.

Ihr Code kompiliert, wenn Sie hinzufügen:

Knoten(const Knoten& anderer) = default; 
Knoten& operator=(const Knoten& anderer) = default; 

und

Kante(const Kante& anderer) = default; 

aber ich bin nicht sicher, ob Standard-Logik für Ihre Klassen ausreichend ist. Sie sollten auch denken, wenn Sie wirklich Ihre eigenen Move Konstruktoren/Operatoren hier benötigen.

+0

Es funktioniert - zumindest ohne die hier beschriebenen Fehler. Da ich ein wenig unter Zeitdruck bin, werde ich die Möglichkeit, die zusätzlichen Funktionen wegzulassen, nicht weiter untersuchen (es funktioniert nicht beim ersten Versuch und wurde im cppreference.com-Beispiel für emplace_back angegeben). Vielen Dank. – user7427029

3

Knoten Graph::naechster_Nachbar(Knoten&) kehrt nach Wert, und so versucht, die Knoten zu kopieren. Aber es kann nicht, weil die Klasse nur einen Bewegungskonstruktor und keinen Kopierkonstruktor hat.

Interessanterweise kopiert der Move-Konstruktor tatsächlich alle Daten von anderer, also könnte es einfach ein Kopierkonstruktor gewesen sein.

+0

Vielen Dank für die schnelle Antwort! Ich werde morgen versuchen, den Move-Konstruktor in einen Copy-Konstruktor zu ändern. – user7427029

Verwandte Themen