boost :: variant; std :: unique_ptr和copy [英] boost::variant; std::unique_ptr and copy

查看:168
本文介绍了boost :: variant; std :: unique_ptr和copy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



class

  template< class T = int> 

class Tree {

private:

类TreeNode {

public:
std :: unique_ptr节点
移动构造函数和移动赋值+其他公共成员

private:

TreeNode(const TreeNode& other); (=编译器不支持删除)
TreeNode& operator =(const TreeNode& rhs); (=编译器不支持删除)


}; // End Tree Node Class Definition


Tree(const Tree& other); (=编译器不支持删除)
Tree& operator =(const Tree& rhs); (=编译器不支持删除)

public:

移动构造函数并移动赋值语句+其他公共成员
};

TreeVisitor class

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

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

};

TreeVariant

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

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

应用访问者如下

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

对于所需的参数

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

类型的编译器错误

tree = stringTree; < --------与赋值相关的错误

/ code>正确编译并已测试。如何解决这些编译错误,这些错误与尝试获取 Tree 类的副本相关,因为 std :: unique_ptr

  

< 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 ){}

friend类Tree;

private:

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

std :: unique_ptr< TreeNode>剩下;
std :: unique_ptr< TreeNode>对;

}; //结束树节点类定义

std :: unique_ptr< TreeNode>根;

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


public:

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

〜Tree(){}

Tree(BinarySearchTree& amp; 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()){
//抓取第一个实例
keyIndex = instances.at(0) ;
//计算要删除的元组的结束
endIndex = keyIndex + sizeToDelete;

//读取第一个属性
try {
temp = boost :: trim_copy(dataFile-> readData(keyIndex,domainSize));
}
catch(std :: exception& e){
printw(从数据文件读取时出错);
}

//从数据文件中删除tuple
if(!dataFile-> deleteTuple(keyIndex,endIndex)){
printw元组);
if(writer_!= nullptr)
writer_<< 尝试删除元组时出错;
try {
printw(%s);
//关闭目录和搜索文件

}
catch(std :: exception& e){
e.what
}
//关闭数据文件
dataFile-> closeFile();
return false;
}


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

searchTree = intSearchTree;

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

//从索引文件中删除键索引
if(!boost :: apply_visitor(BinarySearchTreeVisitor(),searchTree)){
printw );
try {
printw();

}
catch(std :: exception& e){

}
//关闭数据文件
dataFile-> closeFile();
return false;
}
}
catch(boost :: bad_lexical_cast& e){

/ *
*必须是std :: string ---哇谁知道
* /

searchTree = stringSearchTree;

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

//从索引文件中删除键索引
if(!boost :: apply_visitor(BinarySearchTreeVisitor(),searchTree)){
printw(索引文件中没有索引);
try {
printw();
//关闭目录和搜索文件

}
catch(std :: exception& e){
e.what
}
//关闭数据文件
dataFile-> closeFile();
return false;
}

}

//清理索引文件
boost :: bind(BinarySearchTreeVisitor(),searchTree,keyIndex,sizeToDelete);
boost :: apply_visitor(BinarySearchTreeVisitor(),searchTree);

instances.erase(instances.begin());

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

}
}


方案

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

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

但是,这里有一个更大的问题: boost :: variant 只能保存可复制构造的类型。从 Boost.Variant在线文档


有界类型的要求如下:




  • CopyConstructible [20.1.3]。


  • 破坏者维护无异常安全保证。


  • 在变体模板实例化时完成。 ( boost :: recursive_wrapper< T> 适用于接受不完全类型以启用递归变量类型的类型包装器。)




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



This Question Determined That a Non-Copyable Type Can't Be Used With Boost Variant

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;

Applying Visitors as follows

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

Also using boost::bind for desired parameters

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

Compiler errors of the type

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 resolve these compilation errors that appear related to trying to obtain a copy of the Tree class which, because of std::unique_ptr, is just not possible?

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


};

Example use:

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

                }
}

解决方案

Concerning the call to boost::bind(), you should use boost::ref() when passing an object by reference to a function template that accepts the corresponding argument by value, otherwise a copy will be attempted (which results in a compiler error in this case, since the copy constructor is inaccessible):

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

However, there is a bigger problem here: boost::variant can only hold types which are copy-constructible. From the Boost.Variant online documentation:

The requirements on a bounded type are as follows:

  • CopyConstructible [20.1.3].

  • Destructor upholds the no-throw exception-safety guarantee.

  • Complete at the point of variant template instantiation. (See boost::recursive_wrapper<T> for a type wrapper that accepts incomplete types to enable recursive variant types.)

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

这篇关于boost :: variant; std :: unique_ptr和copy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆