C ++ Using deleted function error
I am getting a lot of benefit from the deleted function error. I just changed the pointer weighted_pointer
to unique_ptr
. But I can't figure out why I am getting an error, any feedback?
likeatree
is a DAG structure that can point to another structure or element stdDeque
based on a mask value.
weight
weighted_pointer
has a keyword mutable
because it 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 one case of problem Edit: Solved. No dereferencing when using make_unique.
source to share
Your structure is 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 full weighted_pointer
one cannot be copied either.
There are three places in your code where you are trying to copy it, which is causing errors:
bool operator()(const weighted_pointer lhs, const weighted_pointer rhs) {
Should be:
bool operator()(weighted_pointer const& lhs, weighted_pointer const& rhs) {
stdSet.insert(tmp);
This could theoretically be fixed with:
stdSet.insert(std::move(tmp));
However, you will no longer be able to use tmp
what you are doing, not only in the same loop, but also in the loop below. Therefore, you must find another solution. Maybe use emplace
. Or rebuild your code completely.
auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer temp){ return temp.ptr.get() == treeVector[i]; });
Should be:
auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer const& temp){ return temp.ptr.get() == treeVector[i]; });
For VC ++ 2013, the fix std::move
will not be sufficient. You will need to add an explicit move mechanism to your structure:
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
source to share
Yours is weighted_pointer
not copied because it contains a non-copyable element ( unique_ptr
), so you need 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 currently written) it will try to create a local-local copy.
You also cannot do this because you are trying to copy tmp
, which, as I said, is struct
not 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 create weighted_pointer
instead
for(unsigned int i = 0; i < stdDeque.size(); i++){
stdSet.emplace(1, std::make_unique<likeatree>(0,&stdDeque[i],nullptr));
}
source to share
When I compile the code above, the compiler says:
In file included from /usr/include/c++/4.8/algorithm:62:0,
from 31791982.cpp:7:
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of โ_InputIterator std::__find_if(_InputIterator, _InputIterator, _Predicate, std::input_iterator_tag) [with _InputIterator = std::_Rb_tree_const_iterator<weighted_pointer>; _Predicate = main()::__lambda0]โ:
/usr/include/c++/4.8/bits/stl_algo.h:4465:41: required from โ_IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter = std::_Rb_tree_const_iterator<weighted_pointer>; _Predicate = main()::__lambda0]โ
31791982.cpp:55:124: required from here
So, look at line 55 - what's going on:
auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer temp){ return temp.ptr.get() == treeVector[i]; });
We are trying to copy weighted_pointer
from array to lambda temp
. But in fact, we'd be happy with the ref constant, so we const weighted_pointer&
'll replace it with and compile again:
/usr/include/c++/4.8/bits/stl_tree.h: In instantiation of โstd::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_unique_pos(const key_type&) [with _Key = weighted_pointer; _Val = weighted_pointer; _KeyOfValue = std::_Identity<weighted_pointer>; _Compare = ptrcomp; _Alloc = std::allocator<weighted_pointer>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type = weighted_pointer]โ:
/usr/include/c++/4.8/bits/stl_tree.h:1377:47: required from โstd::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = const weighted_pointer&; _Key = weighted_pointer; _Val = weighted_pointer; _KeyOfValue = std::_Identity<weighted_pointer>; _Compare = ptrcomp; _Alloc = std::allocator<weighted_pointer>]โ
/usr/include/c++/4.8/bits/stl_set.h:463:29: required from โstd::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const value_type&) [with _Key = weighted_pointer; _Compare = ptrcomp; _Alloc = std::allocator<weighted_pointer>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<weighted_pointer>; std::set<_Key, _Compare, _Alloc>::value_type = weighted_pointer]โ
31791982.cpp:49:26: required from here
Line 49:
stdSet.insert(tmp);
We cannot copy tmp
to a set. If we weren't going to reuse tmp
, we could have moved it instead:
for(unsigned int i = 0; i < stdDeque.size(); i++){
weighted_pointer tmp;
tmp.weight = 1;
tmp.ptr.reset(new likeatree{0,&stdDeque[i],nullptr});
stdSet.insert(std::move(tmp));
}
This way we leave us no problem for ptrcomp::operator()
which must accept its arguments by const reference.
source to share