提高::变体; std :: unique_ptr和copy

时间:2013-03-28 18:43:42

标签: c++ c++11 unique-ptr boost-variant

此问题确定不可复制的类型不能与Boost变体一起使用

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

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

还使用boost :: bind作为所需参数

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 个答案:

答案 0 :(得分:6)

关于对boost::bind()的调用,在通过引用传递对象时,应使用boost::ref(),该函数模板按值接受相应的参数,否则 copy 将尝试(在这种情况下导致编译器错误,因为复制构造函数不可访问):

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

但是,这里存在一个更大的问题:boost::variant只能包含可复制构造的类型。来自Boost.Variant online documentation

  

对有界类型的要求如下:

     
      
  • CopyConstructible [20.1.3]。

  •   
  • Destructor坚持无抛出异常安全保证。

  •   
  • 在变体模板实例化时完成。 (有关接受不完整类型的类型包装器,请参阅boost::recursive_wrapper<T>以启用递归变体类型。)

  •   
     

指定为variant的模板参数的每种类型都必须至少满足上述要求。 [...]

答案 1 :(得分: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)。