2013-03-28 19 views
6

Diese Frage bestimmt, dass ein nicht kopierbaren Typ kann nicht mit Boost-Variante verwendet wirdboost :: variante; std :: unique_ptr und Kopie

Tree Klasse

template <class T = int> 

class Tree{ 

private: 

     class TreeNode{ 

     public: 
       std::unique_ptr Nodes 
       Move constructors and move assignment + other public members 

     private: 

       TreeNode(const TreeNode &other);  (= delete not supported on compiler) 
       TreeNode& operator=(const TreeNode &rhs); (= delete not supported on compiler) 


     }; // End Tree Node Class Definition 


     Tree(const Tree &other);  (= delete not supported on compiler) 
     Tree& operator=(const Tree &rhs); (= delete not supported on compiler) 

public: 

     Move constructors and move assignment + other public members 
}; 

TreeVisitor Klasse

class TreeVisitor : public boost::static_visitor<bool> { 
public: 
     TreeVisitor() {} 

     bool operator() (BinarySearchTree<std::string>& tree) const { 
      return searchTree.load(tree); 
     } 
private: 

}; 

TreeVariant

typedef boost::variant<Tree<std::string>, Tree<int>> TreeVariant;  
TreeVariant tree; 

Tree<std::string> stringTree; 
Tree<int> intTree; 

Visitors Anwendung als

tree = intSearchTree; 
boost::apply_visitor(TreeVisitor(), tree) 

Auch mit boost :: bind folgt für die gewünschten Parameter

boost::bind(TreeVisitor(), tree, val, keyIndex); 

Compiler Fehler des Typs

error C2248: 'Tree<T>::Tree' : cannot access private member declared in class 'Tree<T>' <----- related to private copy constructor in Tree (not TreeNode) 
tree = stringTree; <------- error related to assignment 

Tree richtig kompiliert und getestet wurde . Wie kann ich diese Kompilierungsfehler beheben, die im Zusammenhang mit dem Versuch stehen, eine Kopie der Tree-Klasse zu erhalten, die aufgrund von std::unique_ptr nicht möglich ist?

SSCCE

<class T = int> 

class Tree{ 

private: 

class TreeNode{ 

public: 

    TreeNode() {} 
    ~TreeNode() {} 

    TreeNode(TreeNode &&other) : 
     key(other.key), index(other.index), left(std::move(other.left)), right(std::move(other.right)) 
    { 
     key = index = left = right = nullptr; 
    } 

    TreeNode &operator=(BTreeNode &&rhs) 
    { 
     if(this != &rhs) 
     { 
      key = rhs.key; index = rhs.index; 
      left = std::move(rhs.left); right = std::move(rhs.right); 
      rhs.key = rhs.index = rhs.left = rhs.right = nullptr; 
     } 
     return *this; 
    } 

    TreeNode(const T &new_key, const T &new_index) : 
     key(new_key), index(new_index), left(nullptr), right(nullptr) {} 

    friend class Tree; 

private: 

    TreeNode(const BinarySearchTreeNode &other); 
    TreeNode& operator=(const BinarySearchTreeNode &rhs); 

    std::unique_ptr<TreeNode> left; 
    std::unique_ptr<TreeNode> right; 

}; // End Tree Node Class Definition 

std::unique_ptr<TreeNode> root; 

BinarySearchTree(const BinarySearchTree &other); 
BinarySearchTree& operator=(const BinarySearchTree &rhs); 


public: 

Tree() : root(nullptr), flag(false), run(true), leftCount(0), rightCount(0) {} 

~Tree() {} 

Tree(BinarySearchTree &&other) : root(std::move(other.root)) { other.root = nullptr; } 

Tree &operator=(BinarySearchTree &&rhs) 
{ 
    if(this != &rhs) 
    { 
     root = std::move(rhs.root); 
     rhs.root = nullptr; 
    } 
    return *this; 
} 


}; 

Beispiel Verwendung:

bool delete_(){ 

    while(!instances.empty()){ 
        // grab first instance 
        keyIndex = instances.at(0); 
        // compute end of the tuple to delete 
        endIndex = keyIndex + sizeToDelete; 

        // read the first attribute 
        try{ 
         temp = boost::trim_copy(dataFile->readData(keyIndex, domainSize)); 
        } 
        catch (std::exception &e){ 
         printw("Error reading from the data file"); 
        } 

        // delete tuple from data file 
        if(!dataFile->deleteTuple(keyIndex, endIndex)){ 
         printw("Error attempting to remove tuple"); 
         if (writer_ != nullptr) 
          writer_ << "Error attempting to remove tuple"; 
         try{ 
          printw("%s"); 
          // close catalog and search file 

         } 
         catch (std::exception &e){ 
          e.what(); 
         } 
         // close data file 
         dataFile->closeFile(); 
         return false; 
        } 


        try{ 
         int val = boost::lexical_cast<int>(temp); 

         searchTree = intSearchTree; 

         boost::bind(BinarySearchTreeVisitor(), searchTree, val, keyIndex); 

         // delete key index from the index file 
         if (!boost::apply_visitor(BinarySearchTreeVisitor(), searchTree)){ 
          printw("No index present in index file"); 
          try{ 
           printw(" "); 

          } 
          catch (std::exception &e){ 

          } 
          // close data file 
          dataFile->closeFile(); 
          return false;   
         } 
        } 
        catch(boost::bad_lexical_cast &e){ 

         /* 
         * Must be a std::string --- wow who knew 
         */ 

         searchTree = stringSearchTree; 

         boost::bind(BinarySearchTreeVisitor(), searchTree, temp, keyIndex); 

         // delete key index from the index file 
         if (!boost::apply_visitor(BinarySearchTreeVisitor(), searchTree)){ 
          printw("No index present in index file"); 
          try{ 
           printw(" "); 
           // close catalog and search file 

          } 
          catch (std::exception &e){ 
           e.what(); 
          } 
          // close data file 
          dataFile->closeFile(); 
          return false;   
         } 

        }      

        // clean up the index file 
        boost::bind(BinarySearchTreeVisitor(), searchTree, keyIndex, sizeToDelete); 
        boost::apply_visitor(BinarySearchTreeVisitor(), searchTree); 

        instances.erase(instances.begin()); 

        for(int i= 0; i < instances.size(); i++){ 
         instances.assign(i, instances.at(i) - 
                  sizeToDelete); 
        } 

       } 
} 
+2

Postleitzahl, die bitte kompiliert. (und zeigt immer noch das Problem) Löschen Sie Dinge, die nicht wichtig sind, aber immer noch das Problem zeigen. Sehen Sie hier: http://sscce.org/ für Schritte, um Ihre Frage leichter zu beantworten. – Yakk

+0

@Yakk Mein Originalbeitrag zeigt das Problem so klar wie möglich für ein Programm mit zehn Klassen und Tausenden von Codezeilen. Es ist so gut wie es geht, ohne dass Sie ad infinitum scrollen. – Mushy

+0

Nein, ist es nicht. Ihr 'TreeVisitor' spricht von' BinarySearchTree', einem Typ, der aus dem Nichts kommt. Ist 'Tree' angeblich' BinarySearchTree'? Fast alle Ihre "delete_" -Funktion ist für das Problem nicht relevant, wie ist das so kurz wie Sie es bekommen können? Haben die Mitglieder von 'TreeNode' etwas mit dem Problem zu tun? Ich bezweifle das. Der ganze Sinn eines kurzen, eigenständigen Kompilierungsbeispiels besteht darin, dass Sie tatsächlich Code schreiben, der * compiliert * s und das Problem demonstriert, und alles, was Sie eliminieren können, daraus entfernt, während das Problem noch demonstriert wird. Das kannst du besser. – Yakk

Antwort

5

die Aufforderung zu boost::bind(), sollten Sie boost::ref() verwenden, wenn ein Objekt unter Bezugnahme auf eine Funktionsschablone verläuft, die das entsprechende Argument durch den Wert annimmt, andernfalls wird eine Kopie versucht (was in diesem Fall zu einem Compilerfehler führt, da auf den Kopierkonstruktor nicht zugegriffen werden kann):

Allerdings gibt es hier ein größeres Problem: boost::variant kann nur Typen enthalten, die kopierfähig sind. Von der Boost.Variant online documentation:

Die Anforderungen an einen beschränkten Typs sind wie folgt:

  • CopyConstructible [20.1.3].

  • Destructor hält die No-Throw-Ausnahmesicherheitsgarantie aufrecht.

  • Vollständig am Punkt der Instanziierung der Variantenvorlage. (Siehe boost::recursive_wrapper<T> für eine Art Wrapper, der unvollständigen Typen akzeptiert rekursive Variante Typen zu ermöglichen.)

Jeder Typ als Template-Argument angegeben variant mindestens müssen die oben genannten Anforderungen erfüllen. [...]

+0

Ich benutzte 'std :: ref' um' tree' gewickelt und der Compiler gab eine 'error C2558: Klasse 'aus boost :: _ bi :: list3 ': kein Kopierkonstruktor verfügbar oder Kopierkonstruktor wird 'explizit'' 'mit deklariert A1 = boost :: _bi :: value A2 = boost :: _ bi :: wert , A3 = boost :: _ bi :: wert Mushy

+0

@Mushy: Wie wäre es 'boost :: ref dann ? Wenn das nicht funktioniert, werde ich diese Antwort löschen –

+0

Scheint zu arbeiten; compiler states 'error C2248: 'Baum :: Tree': kann nicht auf das private Member zugreifen, das in der Klasse 'Tree ' deklariert wurde und hat ein Problem mit' tree = stringTree', was meiner Meinung nach eine 'std :: move' erfordert. – Mushy

1
using Mixed = boost::variant< 
    std::unique_ptr<char>, 
    std::unique_ptr<short>, 
    std::unique_ptr<int>, 
    std::unique_ptr<unsigned long> 
>; 

int main() {  
    auto md = std::unique_ptr<int>(new int(123)); 
    Mixed mixed = std::move(md); 
    std::cout << *boost::get< std::unique_ptr<int> >(mixed) << std::endl; 
    return 0; 
} 

unique_ptr ist bewegen geschützt und kann in Variante verwendet werden. Das obige Beispiel kann kompilieren und arbeiten (C++ 11).

Verwandte Themen