C++ Use of deleted function error

27,720

Solution 1

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)

Solution 2

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));
}
Share:
27,720
Umuril Lyerood
Author by

Umuril Lyerood

Updated on August 04, 2020

Comments

  • Umuril Lyerood
    Umuril Lyerood over 3 years

    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.