Promotion :: option; std :: unique_ptr and copy

This question defines that a non-copyable type cannot be used with the Boost option.

Tree class

 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

 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 application as follows

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

Also boost :: bind is used for the desired parameters.

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

Type Compiler Errors

 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 compiles correctly and has been tested. How can I solve these compilation errors that appear related to trying to get a copy of the Tree class, which is simply impossible due to 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; } }; 

Usage example:

 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); } } } 
+6
source share
2 answers

As for calling boost::bind() , you should use boost::ref() when passing an object by reference to a function template that takes an appropriate argument by value, otherwise an attempt will be made to copy (which leads to a compiler error in this case, since the copy constructor is not available):

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

However, there is a big problem: boost::variant can only contain types that can be copied. From Boost.Variant online documentation :

The requirements for the limited type are as follows:

  • CopyConstructible [20.1.3].

  • The destructor maintains a no-throw safety guarantee.

  • It is executed at the time the instance is created. (See boost::recursive_wrapper<T> for a type wrapper that allows incomplete types to include recursive variant types.)

Each type specified as an argument to the variant template must, at a minimum, fulfill the above requirements . [...]

+5
source
 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 is only for moving and can be used in a variant. The above example can compile and work (C ++ 11).

+1
source

All Articles