повышение :: вариант; std :: unique_ptr и скопировать

Этот вопрос определил, что непечатаемый тип не может использоваться с Boost Variant

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

}
}

8

Решение

По поводу звонка boost::bind(), вы должны использовать boost::ref() при передаче объекта по ссылке на шаблон функции, который принимает соответствующий аргумент по значению, в противном случае копия будет предпринята попытка (что приведет к ошибке компилятора в этом случае, так как конструктор копирования недоступен):

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

Однако здесь есть большая проблема: boost::variant может содержать только те типы, которые можно копировать. От Boost.Variant онлайн документация:

Требования к ограниченному типу следующие:

  • CopyConstructible [20.1.3].

  • Деструктор поддерживает гарантию безопасности исключений.

  • Завершить в точке создания варианта шаблона. (Увидеть boost::recursive_wrapper<T> для оболочки типов, которая принимает неполные типы для включения рекурсивных типов вариантов.)

Каждый тип, указанный в качестве аргумента шаблона variant должен как минимум соответствовать вышеуказанным требованиям. […]

6

Другие решения

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).

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector