I hate copypasting the whole log here but I can't understand what these errors mean...
I understand some of them have to do with the way I'm using the unique_ptr, but since my IDE doesn't directly point out the incriminated lines I don't know what to do.
In file included from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/i686-w64-mingw32/bits/c++allocator.h:33,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/allocator.h:46,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/string:41,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/locale_classes.h:40,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/ios_base.h:41,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/ios:42,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/ostream:38,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/iostream:39,
from C:\Users\Andrea\CLionProjects\Final_Project_2nd\Column.h:8,
from C:\Users\Andrea\CLionProjects\Final_Project_2nd\Tab.h:8,
from C:\Users\Andrea\CLionProjects\Final_Project_2nd\Tab.cpp:5:
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >; _Args = {const std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Column, std::default_delete<Column> > >&}; _Tp = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >]':
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/alloc_traits.h:475:4: required from 'static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >; _Args = {const std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Column, std::default_delete<Column> > >&}; _Tp = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > > >]'
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h:637:32: required from 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_construct_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, _Args&& ...) [with _Args = {const std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Column, std::default_delete<Column> > >&}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >*]'
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h:506:3: required from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Reuse_or_alloc_node::operator()(_Arg&&) [with _Arg = const std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >&; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >*]'
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h:677:33: required from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_clone_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type, _NodeGen&) [with _NodeGen = std::_Rb_tree<std::__cxx11::basic_string<char>, std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >, std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > > >::_Reuse_or_alloc_node; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >*; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type = const std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >*]'
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h:1834:13: required from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_copy(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, _NodeGen&) [with _NodeGen = std::_Rb_tree<std::__cxx11::basic_string<char>, std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >, std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > > >::_Reuse_or_alloc_node; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >*; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type = const std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >*; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr = std::_Rb_tree_node_base*]'
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h:891:15: required from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_copy(const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&, _NodeGen&) [with _NodeGen = std::_Rb_tree<std::__cxx11::basic_string<char>, std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >, std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > > >::_Reuse_or_alloc_node; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >*]'
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h:1742:16: required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::operator=(const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&) [with _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> >; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::unique_ptr<Column> > >]'
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_map.h:100:11: required from here
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/ext/new_allocator.h:136:4: error: use of deleted function 'constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const std::__cxx11::basic_string<char>; _T2 = std::unique_ptr<Column>]'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_algobase.h:64,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/char_traits.h:39,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/ios:40,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/ostream:38,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/iostream:39,
from C:\Users\Andrea\CLionProjects\Final_Project_2nd\Column.h:8,
from C:\Users\Andrea\CLionProjects\Final_Project_2nd\Tab.h:8,
from C:\Users\Andrea\CLionProjects\Final_Project_2nd\Tab.cpp:5:
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_pair.h:292:17: note: 'constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const std::__cxx11::basic_string<char>; _T2 = std::unique_ptr<Column>]' is implicitly deleted because the default definition would be ill-formed:
constexpr pair(const pair&) = default;
^~~~
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_pair.h:292:17: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Column; _Dp = std::default_delete<Column>]'
In file included from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/locale_conv.h:41,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/locale:43,
from C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/iomanip:43,
from C:\Users\Andrea\CLionProjects\Final_Project_2nd\Date.h:12,
from C:\Users\Andrea\CLionProjects\Final_Project_2nd\DateColumn.h:8,
from C:\Users\Andrea\CLionProjects\Final_Project_2nd\Tab.h:14,
from C:\Users\Andrea\CLionProjects\Final_Project_2nd\Tab.cpp:5:
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/unique_ptr.h:394:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^~~~~~~~~~
mingw32-make.exe[3]: *** [CMakeFiles\Final_Project_2nd.dir\build.make:179: CMakeFiles/Final_Project_2nd.dir/Tab.cpp.obj] Error 1
mingw32-make.exe[3]: *** Waiting for unfinished jobs....
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:75: CMakeFiles/Final_Project_2nd.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:82: CMakeFiles/Final_Project_2nd.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:117: Final_Project_2nd] Error 2
This is Tab.h:
class Tab {
public:
Tab();
~Tab();
void addColumn(string name, string type);
void addRecord(string column);
void operator=(const Tab& to_assign);
private:
map<string, unique_ptr<Column>> _columns;
int _primary_key;
};
And these are two methods:
void Tab::addColumn(string name, string type) {
// I switch all the different types and create a new element on the columns map
// depending on what is the result
switch(Type2Int(type)) {
case OptionInt:
_columns[name].reset(new IntColumn());
break;
case OptionFloat:
_columns[name].reset(new FloatColumn());
break;
case OptionChar:
_columns[name].reset(new CharColumn());
break;
case OptionText:
_columns[name].reset(new TextColumn());
break;
case OptionTime:
_columns[name].reset(new TimeColumn());
break;
case OptionDate:
_columns[name].reset(new DateColumn());
break;
}
}
void Tab::operator=(const Tab &to_assign) {
_columns = to_assign._columns;
}
ColumnImpl class:
template <typename T> class ColumnImpl : public Column {
public:
ColumnImpl();
ColumnImpl(const T& to_set);
vector<T> const& getData() const { return _data; }
void addElem(const T& elem_to_add);
void operator=(const ColumnImpl& to_assign);
protected:
vector<T> _data;
};
And this is a supsect method:
template<typename T>
void ColumnImpl<T>::operator=(const ColumnImpl &to_assign) {
_data = to_assign._data;
}
Database.h:
class Database {
public:
Database();
~Database();
void createNewTable(string name);
void addColumnToTab(string tab_name, string col_name, string type);
private:
map<string, Tab> _tables;
};
These are the only two methods I've implemented:
void Database::createNewTable(string name) {
_tables[name] = Tab();
}
void Database::addColumnToTab(string tab_name, string col_name, string type) {
const auto & it_target_tab = _tables.find(tab_name);
it_target_tab->second.addColumn(col_name, type);
}
Related
Consider this code
#include <map>
#include <memory>
using int_map = std::map<int, std::unique_ptr<int>>;
void f(int_map cl);
void f2() {
int_map cl;
f(cl);
}
Obviously this code does not compile because int_map cannot be copied
But when you compile using gcc:
g++ -Wall -c example.cpp
You get this:
In file included from /usr/include/c++/12.1.1/x86_64-pc-linux-gnu/bits/c++allocator.h:33,
from /usr/include/c++/12.1.1/bits/allocator.h:46,
from /usr/include/c++/12.1.1/bits/stl_tree.h:64,
from /usr/include/c++/12.1.1/map:60,
from example.cpp:1:
/usr/include/c++/12.1.1/bits/new_allocator.h: In instantiation of ‘void std::__new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const int, std::unique_ptr<int> >; _Args = {const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&}; _Tp = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int> > >]’:
/usr/include/c++/12.1.1/bits/alloc_traits.h:516:17: required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::construct(allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const int, std::unique_ptr<int> >; _Args = {const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&}; _Tp = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int> > >; allocator_type = std::allocator<std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int> > > >]’
/usr/include/c++/12.1.1/bits/stl_tree.h:595:32: required from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_construct_node(_Link_type, _Args&& ...) [with _Args = {const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&}; _Key = int; _Val = std::pair<const int, std::unique_ptr<int> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int> > >; _Link_type = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int> > >*]’
/usr/include/c++/12.1.1/bits/stl_tree.h:612:21: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&}; _Key = int; _Val = std::pair<const int, std::unique_ptr<int> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int> > >; _Link_type = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int> > >*]’
/usr/include/c++/12.1.1/bits/stl_tree.h:529:32: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Alloc_node::operator()(_Arg&&) const [with _Arg = const std::pair<const int, std::unique_ptr<int> >&; _Key = int; _Val = std::pair<const int, std::unique_ptr<int> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int> > >*]’
/usr/include/c++/12.1.1/bits/stl_tree.h:645:18: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_clone_node(_Link_type, _NodeGen&) [with bool _MoveValue = false; _NodeGen = std::_Rb_tree<int, std::pair<const int, std::unique_ptr<int> >, std::_Select1st<std::pair<const int, std::unique_ptr<int> > >, std::less<int>, std::allocator<std::pair<const int, std::unique_ptr<int> > > >::_Alloc_node; _Key = int; _Val = std::pair<const int, std::unique_ptr<int> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int> > >; _Link_type = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int> > >*]’
/usr/include/c++/12.1.1/bits/stl_tree.h:1895:47: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_copy(_Link_type, _Base_ptr, _NodeGen&) [with bool _MoveValues = false; _NodeGen = std::_Rb_tree<int, std::pair<const int, std::unique_ptr<int> >, std::_Select1st<std::pair<const int, std::unique_ptr<int> > >, std::less<int>, std::allocator<std::pair<const int, std::unique_ptr<int> > > >::_Alloc_node; _Key = int; _Val = std::pair<const int, std::unique_ptr<int> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int> > >; _Link_type = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int> > >*; _Base_ptr = std::_Rb_tree_node_base*]’
/usr/include/c++/12.1.1/bits/stl_tree.h:890:26: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_copy(const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&, _NodeGen&) [with bool _MoveValues = false; _NodeGen = std::_Rb_tree<int, std::pair<const int, std::unique_ptr<int> >, std::_Select1st<std::pair<const int, std::unique_ptr<int> > >, std::less<int>, std::allocator<std::pair<const int, std::unique_ptr<int> > > >::_Alloc_node; _Key = int; _Val = std::pair<const int, std::unique_ptr<int> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int> > >; _Link_type = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int> > >*]’
/usr/include/c++/12.1.1/bits/stl_tree.h:901:29: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_copy(const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&) [with _Key = int; _Val = std::pair<const int, std::unique_ptr<int> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int> > >; _Link_type = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int> > >*]’
/usr/include/c++/12.1.1/bits/stl_tree.h:939:23: required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Rb_tree(const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&) [with _Key = int; _Val = std::pair<const int, std::unique_ptr<int> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int> > >]’
/usr/include/c++/12.1.1/bits/stl_map.h:217:7: required from here
/usr/include/c++/12.1.1/bits/new_allocator.h:175:11: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<int>]’
175 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/12.1.1/bits/stl_algobase.h:64,
from /usr/include/c++/12.1.1/bits/stl_tree.h:63:
/usr/include/c++/12.1.1/bits/stl_pair.h:195:17: note: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<int>]’ is implicitly deleted because the default definition would be ill-formed:
195 | constexpr pair(const pair&) = default; ///< Copy constructor
| ^~~~
/usr/include/c++/12.1.1/bits/stl_pair.h:195:17: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
In file included from /usr/include/c++/12.1.1/memory:76,
from example.cpp:2:
/usr/include/c++/12.1.1/bits/unique_ptr.h:514:7: note: declared here
514 | unique_ptr(const unique_ptr&) = delete;
| ^~~~~~~~~~
You will usually find tons of rubbish.
But WAIT in most cases we can filter out what we need using some tools
So try this
g++ -Wall -c example.cpp 2>&1 |grep example.cpp
We only care about errors in our code, so we can grep useful information by file name
But SADLY the command above prints this
from example.cpp:1:
from example.cpp:2:
This does not help AT ALL since we know clearly there are no error at line 1 and line 2 in example.cpp
We need the compiler to tell us where the error is, but it doesn't
It is impossible for a new c++ learner (even a professional c++ programmer) to locate the actual error at LINE 6 from those long and unreadable error output
Trivia:
Clang does not tell you the corrent error location, either. But if you use libc++ (-stdlib=libc++), it does. So maybe this is not a gcc problem, but a libstdc++ problem?
(This question was originally asked by a different user at Russian SO. I'm reposting it here with minor changes to give it more exposure.)
Consider this code:
#include <map>
#include <variant>
void operator&&(std::variant<int>, std::variant<int>) {}
int main()
{
std::map<int, int> vals;
vals.find(42);
}
Clang (with both libstdc++ and libc++) and MSVC compile it without problems.
Hovewer, GCC 11.1 and newer (including trunk) give this: Run on gcc.godbolt.org
In file included from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/move.h:57,
from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_pair.h:59,
from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_algobase.h:64,
from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_tree.h:63,
from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/map:60,
from <source>:1:
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/type_traits: In instantiation of 'struct std::is_invocable<const std::less<int>&, const int&, const int&>':
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/type_traits:3001:73: required from 'constexpr const bool std::is_invocable_v<const std::less<int>&, const int&, const int&>'
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_tree.h:770:8: required from 'static const _Key& std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_S_key(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type) [with _Key = int; _Val = std::pair<const int, int>; _KeyOfValue = std::_Select1st<std::pair<const int, int> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type = const std::_Rb_tree_node<std::pair<const int, int> >*]'
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_tree.h:1903:36: required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_lower_bound(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, const _Key&) [with _Key = int; _Val = std::pair<const int, int>; _KeyOfValue = std::_Select1st<std::pair<const int, int> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree<int, std::pair<const int, int>, std::_Select1st<std::pair<const int, int> >, std::less<int>, std::allocator<std::pair<const int, int> > >::iterator; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, int> >*; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr = std::_Rb_tree_node_base*]'
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_tree.h:2521:36: required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::find(const _Key&) [with _Key = int; _Val = std::pair<const int, int>; _KeyOfValue = std::_Select1st<std::pair<const int, int> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree<int, std::pair<const int, int>, std::_Select1st<std::pair<const int, int> >, std::less<int>, std::allocator<std::pair<const int, int> > >::iterator]'
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/stl_map.h:1170:25: required from 'std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::find(const key_type&) [with _Key = int; _Tp = int; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree<int, std::pair<const int, int>, std::_Select1st<std::pair<const int, int> >, std::less<int>, std::allocator<std::pair<const int, int> > >::iterator; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]'
<source>:9:14: required from here
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/type_traits:2942:7: error: ambiguous overload for 'operator&&' (operand types are 'std::true_type' {aka 'std::integral_constant<bool, true>'} and 'std::true_type' {aka 'std::integral_constant<bool, true>'})
2942 | static_assert((std::__is_complete_or_unbounded(
| ^~~~~~~~~~~~~
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/type_traits:2942:7: note: candidate: 'operator&&(std::integral_constant<bool, true>::value_type {aka bool}, std::integral_constant<bool, true>::value_type {aka bool})' (built-in)
<source>:4:6: note: candidate: 'void operator&&(std::variant<int>, std::variant<int>)'
4 | void operator &&(std::variant<int>, std::variant<int>) {}
| ^~~~~~~~
What's going on here?
EDIT:
Our operator== overload should be invisible for name lookup from <variant> (except for ADL, which is not involved here), so this is definitely a GCC bug.
#rustyx found GCC bug #51577, which looks very similar. But there's more to it, because that bug was introduced in GCC 4.7.0, while the code above only breaks and 11.1 and newer.
This was a GCC bug, fixed in GCC 12.
Basically I have a map containing some entries. I create the entries with a custom constructor and the default constructor is deleted. In an entry I would like to update a value. This I want to achieve by a reference to the entry and then call the update/set method.
I have the following code:
#include <map>
#include <string>
class CacheEntry
{
public:
CacheEntry() = delete;
CacheEntry(const int value1)
: value1(value1)
{
}
void SetValue2(const int value2)
{
this->value2 = value2;
}
private:
const int value1;
int value2;
};
class Cache
{
public:
void SetValue2(const std::string& name, const int value2)
{
if (entries.count(name) == 0)
{
return;
}
CacheEntry& entry = entries[name];
entry.SetValue2(value2);
}
private:
std::map<std::string,CacheEntry> entries;
};
When I compile, I get the following error:
In file included from /usr/include/c++/9/bits/stl_map.h:63,
from /usr/include/c++/9/map:61,
from test.cpp:1:
/usr/include/c++/9/tuple: In instantiation of ‘std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const std::__cxx11::basic_string<char>; _T2 = CacheEntry]’:
/usr/include/c++/9/tuple:1663:63: required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; _Args2 = {}; _T1 = const std::__cxx11::basic_string<char>; _T2 = CacheEntry]’
/usr/include/c++/9/ext/new_allocator.h:147:4: required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >]’
/usr/include/c++/9/bits/alloc_traits.h:484:4: required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> > >]’
/usr/include/c++/9/bits/stl_tree.h:614:32: required from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_construct_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >*]’
/usr/include/c++/9/bits/stl_tree.h:631:4: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >*]’
/usr/include/c++/9/bits/stl_tree.h:2455:13: required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::__cxx11::basic_string<char>; _Val = std::pair<const std::__cxx11::basic_string<char>, CacheEntry>; _KeyOfValue = std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >]’
/usr/include/c++/9/bits/stl_map.h:499:8: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = CacheEntry; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, CacheEntry> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = CacheEntry; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char>]’
test.cpp:33:36: required from here
/usr/include/c++/9/tuple:1674:70: error: use of deleted function ‘CacheEntry::CacheEntry()’
1674 | second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
| ^
test.cpp:7:3: note: declared here
7 | CacheEntry() = delete;
| ^~~~~~~~~~
Why does the compiler create a new object at CacheEntry& entry = entries[name];? I expect a reference to the already existing object in the map.
I know I can remove the CacheEntry() = delete;, but this is not what I want.
Why does the compiler create a new object at CacheEntry& entry = entries[name];?
map::operator[] creates a new default-constructed entry if the specified key doesn't exist. Even though you are using map::count() to ensure that no new entry will actually be created, the implementation code behind operator[] still has to compile properly. That means if you want to use operator[], the map's entries MUST have a valid default constructor.
Otherwise, don't use operator[] at all, use map::find() instead, eg:
void SetValue2(const std::string& name, const int value2)
{
auto iter = entries.find(name);
if (iter != entries.end())
iter->second.SetValue2(value2);
}
I expect a reference to the already existing object in the map.
Correct - at runtime. But at compile-time, the compiler has no way to know that an object will already exist.
What is the correct way to call the print() method when accessing prime as a value of an std::map:
#include <iostream>
#include <map>
using namespace std;
class Prime {
private:
int n;
public:
Prime(int n): n(n) {}
Prime(const Prime &P) {
n = P.n;
}
void print() {
cout << "value: " << n << endl;
}
};
int main() {
Prime prime(5);
map<string, Prime> myMap;
myMap.emplace("five", prime);
// this line appears to be failing
myMap["five"].print();
return 1;
}
When I run this code $ g++ -std=c++11 main.cpp && ./a.out:
In file included from /usr/include/c++/4.8/bits/stl_map.h:63:0,
from /usr/include/c++/4.8/map:61,
from main.cpp:4:
/usr/include/c++/4.8/tuple: In instantiation of ‘std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&}; long unsigned int ..._Indexes1 = {0ul}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const std::basic_string<char>; _T2 = Prime]’:
/usr/include/c++/4.8/tuple:1079:63: required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&}; _Args2 = {}; _T1 = const std::basic_string<char>; _T2 = Prime]’
/usr/include/c++/4.8/bits/stl_tree.h:140:49: required from ‘std::_Rb_tree_node<_Val>::_Rb_tree_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Val = std::pair<const std::basic_string<char>, Prime>]’
/usr/include/c++/4.8/ext/new_allocator.h:120:4: required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::_Rb_tree_node<std::pair<const std::basic_string<char>, Prime> >; _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::basic_string<char>, Prime> >]’
/usr/include/c++/4.8/bits/alloc_traits.h:254:4: required from ‘static typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::_Rb_tree_node<std::pair<const std::basic_string<char>, Prime> >; _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Alloc = std::allocator<std::_Rb_tree_node<std::pair<const std::basic_string<char>, Prime> > >; typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type = void]’
/usr/include/c++/4.8/bits/alloc_traits.h:393:57: required from ‘static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::_Rb_tree_node<std::pair<const std::basic_string<char>, Prime> >; _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Alloc = std::allocator<std::_Rb_tree_node<std::pair<const std::basic_string<char>, Prime> > >; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]’
/usr/include/c++/4.8/bits/stl_tree.h:408:36: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, Prime>; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, Prime> >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, Prime> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::basic_string<char>, Prime> >*]’
/usr/include/c++/4.8/bits/stl_tree.h:1669:64: required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, Prime>; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, Prime> >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, Prime> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, Prime> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, Prime> >]’
/usr/include/c++/4.8/bits/stl_map.h:484:8: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = std::basic_string<char>; _Tp = Prime; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, Prime> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = Prime; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::basic_string<char>]’
main.cpp:31:15: required from here
/usr/include/c++/4.8/tuple:1090:70: error: no matching function for call to ‘Prime::Prime()’
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
/usr/include/c++/4.8/tuple:1090:70: note: candidates are:
main.cpp:15:3: note: Prime::Prime(const Prime&)
Prime(const Prime &P) {
^
main.cpp:15:3: note: candidate expects 1 argument, 0 provided
main.cpp:13:3: note: Prime::Prime(int)
Prime(int n): n(n) {}
^
main.cpp:13:3: note: candidate expects 1 argument, 0 provided
Writing Prime(int n = 0): n(n) {} is your fix.
Even if you are using emplace, the Prime class is required by the C++ standard to have a default constructor, which yours currently doesn't.
I'm trying to implement a class that represents a connection to a file, hence it should be a non-copyable class. Also, since a filename is required to create the object, I'd like to remove the default constructor.
Here is a simplified definition of such a class :
class Elem
{
public:
Elem() = delete;
Elem(string name) : file(new ifstream(name,ios::in)) {}
Elem(const Elem&) = delete;
Elem& operator=(const Elem& o) = delete;
Elem& operator=(Elem && o)
{
swap(o.file,file);
o.file = nullptr;
}
Elem(Elem &&o) : file(nullptr)
{
swap(file,o.file);
}
~Elem()
{
if(file!=nullptr){
file->close();
delete file;
}
}
protected:
ifstream* file;
};
However, when I try to store such objects in a standard map, the code fails to compile :
int main(){
map<string,Elem> m;
m["file1"] = move(Elem("file1"));
cout<<m.size()<<endl;
return 0;
}
I get the following errors (gcc 4.9.1) :
In file included from /usr/include/c++/4.9.1/bits/stl_map.h:63:0,
from /usr/include/c++/4.9.1/map:61,
from test.cpp:1:
/usr/include/c++/4.9.1/tuple: In instantiation of ‘std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&}; unsigned int ..._Indexes1 = {0u}; _Args2 = {}; unsigned int ..._Indexes2 = {}; _T1 = const std::basic_string<char>; _T2 = Elem]’
/usr/include/c++/4.9.1/tuple:1088:63: required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&}; _Args2 = {}; _T1 = const std::basic_string<char>; _T2 = Elem]’
/usr/include/c++/4.9.1/ext/new_allocator.h:120:4: required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const std::basic_string<char>, Elem>; _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::basic_string<char>, Elem> >]’
/usr/include/c++/4.9.1/bits/alloc_traits.h:253:4: required from ‘static std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::pair<const std::basic_string<char>, Elem>; _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Alloc = std::allocator<std::_Rb_tree_node<std::pair<const std::basic_string<char>, Elem> > >; std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> = void]’
/usr/include/c++/4.9.1/bits/alloc_traits.h:399:57: required from ‘static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::pair<const std::basic_string<char>, Elem>; _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Alloc = std::allocator<std::_Rb_tree_node<std::pair<const std::basic_string<char>, Elem> > >; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]’
/usr/include/c++/4.9.1/bits/stl_tree.h:423:42: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, Elem>; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, Elem> >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, Elem> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::basic_string<char>, Elem> >*]’
/usr/include/c++/4.9.1/bits/stl_tree.h:1790:64: required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<>}; _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, Elem>; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, Elem> >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, Elem> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, Elem> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, Elem> >]’
/usr/include/c++/4.9.1/bits/stl_map.h:519:8: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = std::basic_string<char>; _Tp = Elem; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, Elem> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = Elem; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::basic_string<char>]’
test.cpp:41:14: required from here
/usr/include/c++/4.9.1/tuple:1099:70: erreur: use of deleted function ‘Elem::Elem()’
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
test.cpp:11:5: note: declared here
Elem() = delete;
Any clues about how this could be achieved ? Are their other design flaws in my structure ?
Thanks in advance
What you're doing is:
map<string,Elem> m;
m["file1"] = // this default-constructs an Elem
// and returns a reference to it in the correct spot
move(Elem("file1")); // and THEN move-assigns it
What you need to do:
map<string, Elem> m;
m.emplace("file1", Elem("file1"));
or
m.insert(std::make_pair("file1", Elem("file1"));
or
m.emplace(std::piecewise_construct,
std::forward_as_tuple("file1"),
std::forward_as_tuple("file1"));
As for your design, the comments point out the issue that you're potentially leaking a stream. But this is actually a really easy fix. What you are expressing is unique ownership over a file, where that ownership is transferable. There's a type for that: unique_ptr!
class Elem {
std::unique_ptr<ifstream> file;
public:
Elem() = delete;
Elem(string name) : file(new ifstream(name,ios::in)) {}
Elem(Elem&& ) = default;
Elem& operator=(Elem&& ) = default;
~Elem() = default;
Elem(const Elem&) = delete;
Elem& operator=(const Elem&) = delete;
};
Using unique_ptr makes those default/delete lines not even necessary (except the default constructor one - since that's a requirement you're enforcing), which is even better (see Rule of Zero). I'm just illustrating them for clarity.