Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Use of deleted function error

I'm getting a lot of use of deleted function error. I just changed the pointer of weighted_pointer to unique_ptr. But I can't realize why I'm getting the error, any tip?

The likeatree is a DAG structure which can point to another struct or an element of stdDeque based on mask value.

The weight of weighted_pointer has mutable keyword because doesn't change where in the set will be.

#include <deque>
#include <set>
#include <vector>
#include <iostream>
#include <algorithm>
#include <memory>
#include <chrono>

using namespace std;

struct likeatree{
    unsigned int mask : 3;
    void * a;
    void * b;
};

struct weighted_pointer{
    mutable int weight;
    unique_ptr<likeatree> ptr;
};

struct ptrcomp{
    bool operator()(const weighted_pointer & lhs, const weighted_pointer & rhs) {
        if(lhs.ptr->mask < rhs.ptr->mask)
            return true;
        if(lhs.ptr->mask > rhs.ptr->mask)
            return false;
        if(lhs.ptr -> a < rhs.ptr->a)
            return true;
        if(lhs.ptr->a > rhs.ptr->a)
            return false;
        return lhs.ptr->b < rhs.ptr->b;
    }
};

vector<likeatree *> treeVector;
deque<bool> stdDeque(3);
vector<vector<bool>> boolMatrix{{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};
set<weighted_pointer,ptrcomp> stdSet;

int main(){
    srand(time(NULL));
    likeatree * first_pointer = new likeatree{0,&input[0],nullptr};
    likeatree * second_pointer = first_pointer;
    unique_ptr<likeatree> tmp(first_pointer);
    weighted_pointer wp;
    wp.weight = 1;
    wp.pointer = move(tmp);
    stdSet.insert(move(wp));
    // I'd like to do it inline(or more but with variables that end of scope here), but this don't work. (And i don't keep a copy of the pointer)
    // stdSet.insert(move(weighted_pointer{1,move(make_unique<likeatree>(*new likeatree{0,&input[0],nullptr}))}));
    return 0;   
}

Edit: Changed code with a single case of the problem Edit: Solved. Missing a dereference when using make_unique.

like image 321
Umuril Lyerood Avatar asked Dec 10 '22 21:12

Umuril Lyerood


2 Answers

Your struct here:

struct weighted_pointer{
    mutable int weight;
    unique_ptr<likeatree> ptr;
};

contains a std::unique_ptr. A std::unique_ptr cannot be copied, so your entire weighted_pointer cannot be copied as well.

There are three places in your code where you attempt to copy it, which causes the errors you see:

bool operator()(const weighted_pointer lhs, const weighted_pointer rhs) {

Must be:

bool operator()(weighted_pointer const& lhs, weighted_pointer const& rhs) {
stdSet.insert(tmp);

This could theoretically be fixed by:

stdSet.insert(std::move(tmp));

However, you then cannot use tmp anymore, which you do, not only in the same loop but also in the loop below. So you must find a different solution altogether. Perhaps use emplace. Or restructure your code entirely.

auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer temp){ return temp.ptr.get() == treeVector[i]; });

Must be:

auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer const& temp){ return temp.ptr.get() == treeVector[i]; });

For VC++ 2013, the std::move fix will not suffice. You will have to add an explicit move constructor to your struct:

struct weighted_pointer{
    mutable int weight;
    unique_ptr<likeatree> ptr;

    weighted_pointer() = default;
    weighted_pointer(weighted_pointer&& src) :
        weight(std::move(src.weight)),
        ptr(std::move(src.ptr))
    {
    }
};

VC++ 2015 fixes this problem. More information: Default Move Constructor in Visual Studio 2013 (Update 3)

like image 148
Christian Hackl Avatar answered Dec 13 '22 12:12

Christian Hackl


Your weighted_pointer is non-copyable because it contains a non-copyable member (the unique_ptr), so you have to pass it by const reference to your comparator function.

bool operator()(const weighted_pointer& lhs, const weighted_pointer& rhs)

This is because if you pass it by value (as it is currently written), it will try to make a function-local copy.

You also cannot do this because you are trying to copy tmp, which as I just said that struct is non-copyable.

for(unsigned int i = 0; i < stdDeque.size(); i++){
    tmp.ptr.reset(new likeatree{0,&stdDeque[i],nullptr});
    stdSet.insert(tmp);
}

You can use emplace to construct a weighted_pointer in-place instead

for(unsigned int i = 0; i < stdDeque.size(); i++){
    stdSet.emplace(1, std::make_unique<likeatree>(0,&stdDeque[i],nullptr));
}
like image 36
Cory Kramer Avatar answered Dec 13 '22 12:12

Cory Kramer