[英]boost::variant; std::unique_ptr and copy
This Question Determined That a Non-Copyable Type Can't Be Used With Boost Variant 此问题确定不可复制的类型不能与Boost变体一起使用
Tree
class 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
类
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 应用
Visitors
如下
tree = intSearchTree;
boost::apply_visitor(TreeVisitor(), tree)
Also using boost::bind for desired parameters 还使用boost :: bind获取所需的参数
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. Tree
编译正确并已经过测试。 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? 如何解决这些与尝试获取
Tree
类副本相关的编译错误,因为std::unique_ptr
是不可能的?
SSCCE 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()
的调用,你应该在通过引用传递一个对象时使用boost::ref()
,该函数模板按值接受相应的参数,否则将尝试复制 (这会导致编译器)在这种情况下出错,因为复制构造函数不可访问):
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. 但是,这里存在一个更大的问题:
boost::variant
只能包含可复制构造的类型。 From the Boost.Variant online documentation : 来自Boost.Variant在线文档 :
The requirements on a bounded type are as follows:
有界类型的要求如下:
CopyConstructible
[20.1.3].CopyConstructible
[20.1.3]。Destructor upholds the no-throw exception-safety guarantee.
Destructor坚持无抛出异常安全保证。
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.)(有关接受不完整类型以启用递归变体类型的类型包装器,请参阅
boost::recursive_wrapper<T>
。)Every type specified as a template argument to
variant
must at minimum fulfill the above requirements .指定为
variant
的模板参数的每个类型必须至少满足上述要求 。 [...][...]
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 move-only and can be used in variant. unique_ptr是仅移动的,可以在变体中使用。 The above example can compile and work (C++11).
上面的例子可以编译和工作(C ++ 11)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.