2013-03-28 101 views
6

這個問題確定一個不可複製的類型不能用於與升壓變boost :: variant;的std ::的unique_ptr和複製

Tree

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

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作爲另外使用boost ::綁定爲所需參數如下

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

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

類型

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正確編譯和已通過測試的編譯器錯誤。如何解決這些與試圖獲得Tree類的副本相關的編譯錯誤,這些錯誤由於std::unique_ptr而不可行?

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; 
} 


}; 

實施例使用:

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

請編譯的郵政編碼。 (並且仍然演示問題)刪除不重要的事情,但仍然顯示問題。看看這裏:http://sscce.org/瞭解如何使問題更容易回答。 – Yakk

+0

@Yakk我原來的帖子證明了我的問題十分清楚,可以用於十個班級和數千行代碼的程序。它無需滾動廣告即可獲得。 – Mushy

+0

不,它不是。你的'TreeVisitor'正在談論'BinarySearchTree',這是一種無處不在的類型。 「樹」應該是「BinarySearchTree」嗎?幾乎所有的'delete_'函數都與這個問題無關,那麼這個函數如何儘可能短? 「TreeNode」的成員是否與這個問題有關?我對此表示懷疑。一個簡短的,自包含的編譯示例的全部要點是,你實際編寫的代碼能夠編譯*並演示這個問題,並且可以消除從它中刪除的所有內容,同時仍然可以顯示問題。你可以做得更好。 – Yakk

回答

5

關於呼叫boost::bind(),則應該通過引用傳遞一個目的是,通過值接受相應的參數的函數的模板時使用boost::ref(),否則將嘗試副本(在這種情況下會導致編譯器錯誤,因爲複製構造函數不可訪問):

boost::bind(TreeVisitor(), boost::ref(tree), val, keyIndex); 
//       ^^^^^^^^^^^^^^^^ 

但是,這裏有一個更大的問題:boost::variant只能容納可複製構造的類型。從Boost.Variant online documentation

是上界類型的要求如下:

  • CopyConstructible [20.1.3]。

  • 破壞者堅持不拋異常的安全保證。

  • 在變體模板實例化處完成。 (用於接受不完全類型,以使遞歸變體類型的一個類型包裝見boost::recursive_wrapper<T>。)

指定爲模板參數的每個類型variant必須至少滿足上述要求。 [...]

+0

我利用'std :: ref'環繞着'tree'並且編譯器發佈了'錯誤C2558:class'boost :: _ bi :: list3 ':沒有可用的拷貝構造函數或拷貝構造函數被聲明爲'explicit''' A1 = boost :: _ bi :: value A2 = boost :: _ bi :: value , A3 = boost :: _ bi :: value Mushy

+0

@Mushy:那麼'boost :: ref'怎麼樣呢?如果這不起作用,我會刪除這個答案 –

+0

似乎工作;編譯器狀態錯誤C2248:'樹 ::樹':不能訪問在'樹'類中聲明的私有成員,並且有'tree = stringTree'的問題,我認爲這可能需要一個'std :: move'。 – 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是僅移動和可在變體中使用。上面的例子可以編譯和工作(C++ 11)。

相關問題