I am trying to insert element to unordered_map, which should use move operations, but its not using.
For example:
#include <unordered_map>
#include <memory>
#include <utility>
struct S {
int i;
};
int main(){
std::unordered_map<int, std::unique_ptr<S>> map {};
std::unique_ptr<S> s {new S{1}};
map.insert({1, std::move(s)});
return 0;
}
Compiling it as: g++-6 -std=c++11 -c Ex2.cpp
Getting error:
In file included from /usr/include/x86_64-linux-gnu/c++/6/bits/c++allocator.h:33:0,
from /usr/include/c++/6/bits/allocator.h:46,
from /usr/include/c++/6/string:41,
from /usr/include/c++/6/stdexcept:39,
from /usr/include/c++/6/array:39,
from /usr/include/c++/6/tuple:39,
from /usr/include/c++/6/unordered_map:41,
from Ex2.cpp:1:
/usr/include/c++/6/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const int, std::unique_ptr<S> >; _Args = {const std::pair<const int, std::unique_ptr<S, std::default_delete<S> > >&}; _Tp = std::pair<const int, std::unique_ptr<S> >]’:
/usr/include/c++/6/bits/alloc_traits.h:455: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 int, std::unique_ptr<S> >; _Args = {const std::pair<const int, std::unique_ptr<S, std::default_delete<S> > >&}; _Tp = std::pair<const int, std::unique_ptr<S> >; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::pair<const int, std::unique_ptr<S> > >]’
/usr/include/c++/6/bits/hashtable_policy.h:1953:37: required from ‘std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type* std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&& ...) [with _Args = {const std::pair<const int, std::unique_ptr<S, std::default_delete<S> > >&}; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const int, std::unique_ptr<S> >, false> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::__detail::_Hash_node<std::pair<const int, std::unique_ptr<S> >, false>]’
/usr/include/c++/6/bits/hashtable_policy.h:180:58: required from ‘std::__detail::_AllocNode<_NodeAlloc>::__node_type* std::__detail::_AllocNode<_NodeAlloc>::operator()(_Arg&&) const [with _Arg = const std::pair<const int, std::unique_ptr<S> >&; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const int, std::unique_ptr<S> >, false> >; std::__detail::_AllocNode<_NodeAlloc>::__node_type = std::__detail::_Hash_node<std::pair<const int, std::unique_ptr<S> >, false>]’
/usr/include/c++/6/bits/hashtable.h:1690:18: required from ‘std::pair<typename std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, _Hash, _Traits>::iterator, bool> std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::_M_insert(_Arg&&, const _NodeGenerator&, std::true_type) [with _Arg = const std::pair<const int, std::unique_ptr<S> >&; _NodeGenerator = std::__detail::_AllocNode<std::allocator<std::__detail::_Hash_node<std::pair<const int, std::unique_ptr<S> >, false> > >; _Key = int; _Value = std::pair<const int, std::unique_ptr<S> >; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<S> > >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<int>; _H1 = std::hash<int>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; typename std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, _Hash, _Traits>::iterator = std::__detail::_Node_iterator<std::pair<const int, std::unique_ptr<S> >, false, false>; std::true_type = std::integral_constant<bool, true>]’
/usr/include/c++/6/bits/hashtable_policy.h:713:55: required from ‘std::__detail::_Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__ireturn_type std::__detail::_Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::insert(const value_type&) [with _Key = int; _Value = std::pair<const int, std::unique_ptr<S> >; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<S> > >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<int>; _H1 = std::hash<int>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; std::__detail::_Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__ireturn_type = std::pair<std::__detail::_Node_iterator<std::pair<const int, std::unique_ptr<S> >, false, false>, bool>; std::__detail::_Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::value_type = std::pair<const int, std::unique_ptr<S> >]’
/usr/include/c++/6/bits/unordered_map.h:550:31: required from ‘std::pair<typename std::_Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc, std::__detail::_Select1st, _Pred, _Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<std::__not_<std::__and_<std::__is_fast_hash<_Hash>, std::__detail::__is_noexcept_hash<_Key, _Hash> > >::value, false, true> >::iterator, bool> std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(const value_type&) [with _Key = int; _Tp = std::unique_ptr<S>; _Hash = std::hash<int>; _Pred = std::equal_to<int>; _Alloc = std::allocator<std::pair<const int, std::unique_ptr<S> > >; typename std::_Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc, std::__detail::_Select1st, _Pred, _Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<std::__not_<std::__and_<std::__is_fast_hash<_Hash>, std::__detail::__is_noexcept_hash<_Key, _Hash> > >::value, false, true> >::iterator = std::__detail::_Node_iterator<std::pair<const int, std::unique_ptr<S> >, false, false>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::value_type = std::pair<const int, std::unique_ptr<S> >]’
Ex2.cpp:14:30: required from here
/usr/include/c++/6/ext/new_allocator.h:120:4: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<S>]’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/6/utility:70:0,
from /usr/include/c++/6/unordered_map:38,
from Ex2.cpp:1:
/usr/include/c++/6/bits/stl_pair.h:224:17: note: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<S>]’ is implicitly deleted because the default definition would be ill-formed:
constexpr pair(const pair&) = default;
^~~~
/usr/include/c++/6/bits/stl_pair.h:224:17: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = S; _Dp = std::default_delete<S>]’
In file included from /usr/include/c++/6/memory:81:0,
from Ex2.cpp:2:
/usr/include/c++/6/bits/unique_ptr.h:356:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^~~~~~~~~~
So, error seems telling me that I am using deleted copy constructor of std::pair, which is deleted because std::unique_ptr doesn't have copy constructor. BUT why its not using move constructor?
It compiles fine in my visual studio 2017.
I am using g++ compiler version: gcc version 6.2.0 20160901
Related
Here is my code:
#include <cstdint>
#include <vector>
class Bar {
uint32_t m_value;
public:
Bar(const uint32_t value) : m_value(value) {
}
};
class Foo {
Bar* m_p_bar;
uint32_t m_value;
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
Foo& operator=(Foo&&) = default;
Foo(Foo&&) = default;
public:
/*
Foo(Foo&& from) {
m_p_bar = from.m_p_bar;
m_value = from.m_value;
from.m_p_bar = nullptr;
}
*/
Foo(const uint32_t value) : m_value(value) {
m_p_bar = new Bar(value);
}
};
int main() {
std::vector<Foo> foos;
foos.emplace_back(8);
}
Compiler complains:
In file included from /opt/rh/devtoolset-9/root/usr/include/c++/9/vector:66,
from test_implicit_func.cpp:2:
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h: In instantiation of ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Foo*>; _ForwardIterator = Foo*]’:
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h:307:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<Foo*>; _ForwardIterator = Foo*; _Tp = Foo]’
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h:329:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = Foo*; _ForwardIterator = Foo*; _Allocator = std::allocator<Foo>]’
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/vector.tcc:474:3: required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {int}; _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<Foo*, std::vector<Foo> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = Foo*]’
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/vector.tcc:121:4: required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {int}; _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::reference = Foo&]’
test_implicit_func.cpp:34:21: required from here
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
127 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
| ^~~~~
I noticed that for some reason, I need to define my own move constructor for Foo. By explicitly asking the compiler to use the default one (i.e. Foo(Foo&&) = default;), it doesn't work. However, if I ask the compiler to use all the implicit ones (i.e. removing Foo(const Foo&) = delete; Foo& operator=(const Foo&) = delete; Foo& operator=(Foo&&) = default; Foo(Foo&&) = default;), then compiler doesn't complain.
My question is why explicitly asking compiler to use the default move constructor here doesn't work but it works in this case. And this answer suggests I could ask for a default version if it is implicitly removed.
If you let the compiler use the implicitly defined "big 5" you will have problems with leaks and double free:s.
You need to make the move constructor public and you need to delete the pointer in the destructor. You also need to make sure not to leave the pointer in the moved-from object.
#include <utility> // exchange
class Foo {
Bar* m_p_bar;
uint32_t m_value;
public:
Foo(const uint32_t value) :
m_p_bar(new Bar(value)),
m_value(value)
{}
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
Foo(Foo&& rhs) :
m_p_bar(std::exchange(rhs.m_p_bar, nullptr)), // put a nullptr in rhs
m_value(rhs.m_value)
{}
Foo& operator=(Foo&& rhs) {
std::swap(m_p_bar, rhs.m_p_bar); // let rhs destroy our current Bar
m_value = rhs.m_value;
return *this;
}
~Foo() { delete m_p_bar; } // destroy it
};
A better idea would be to use a std::unique_ptr<Bar> - or to not use a pointer at all.
I have the following piece of code -
#include <map>
using Type1 = std::map<std::string, unsigned long long>;
using Type2 = std::map<std::string, Type1>;
class T
{
private:
Type2 mymap;
public:
const Type1& get(const std::string& key) const;
};
const Type1& T::get(const std::string& key) const
{
return mymap[key];
}
int main(void)
{
}
This does not compile and the compiler complains -
maps.cpp: In member function ‘const Type1& T::get(const string&)
const’: maps.cpp:17:20: error: passing ‘const Type2 {aka const
std::map<std::basic_string<char>, std::map<std::basic_string<char>,
long long unsigned int> >}’ as ‘this’ argument of ‘std::map<_Key, _Tp,
_Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::basic_string<char>; _Tp = std::map<std::basic_string<char>, long
long unsigned int>; _Compare = std::less<std::basic_string<char> >;
_Alloc = std::allocator<std::pair<const std::basic_string<char>, std::map<std::basic_string<char>, long long unsigned int> > >;
std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type =
std::map<std::basic_string<char>, long long unsigned int>;
std::map<_Key, _Tp, _Compare, _Alloc>::key_type =
std::basic_string<char>]’ discards qualifiers [-fpermissive]
return mymap[key];
^
I need help understanding this error. From what I can tell I am not modifying "this" in the get function.
Thanks!
The errors comes from the fact that
std::map::operator[] can
inserts the key if the it does not exist.
You could do a std::map::find first as a check.
I am making a commandline program in C++ and have run into some strange problems.
I am very new to C++, so this is probably why I am so baffled.
I am using MinGW to compile and debug.
Here is the current code:
#include <string>
#include <vector>
#include <iostream>
#include <stdlib.h>
using namespace std;
// Global Vars
string headerSpace = "\t\t";
string instructionSpace = "\t";
string prmpt = "WIO:+>";
string daysOFWeek [7] = {"mon", "tue", "wed", "thur", "fri", "sat", "sun"};
vector<string> commandHelpGet ("To view a day's exercises type:: get (date)\n", "To view today's required exercises type:: get required\n");
vector<string> commandHelpRem ( "To clear a day's record type:: remove (date)\n", "To remove an exercise from your routine type:: remove (name)\n");
vector<string> commandHelpRec ("To record a day's exercises type:: record (date)\n");
vector<string> commandHelpAdd ("To add an exercise to your routine type:: add (name) (rep/min) (daysOFWeek)\n");
// Method prototypes
vector<string> splitString(string input, string splitter);
void processGetCom(vector<string> input);
void processRecordCom(vector<string> input);
void processRemoveCom(vector<string> input);
void processAddCom(vector<string> input);
void help(string context);
void printError(string reason);
string requiredExercises();
string getRecord(string input);
int main()
{
cout << "\n\n" + headerSpace + "---------- Welcome to WorkItOut! ----------\n";
help("");
string inRaw = "";
vector<string> input;
while (true)
{
cout << prmpt;
string inRaw = "";
getline(cin, inRaw);
input = splitString(inRaw, " ");
// Overflow guard
if (input.size() > 4)
{
printError("To many arguments; Please enter a valid command");
}
if (input[0].compare("get") == 0)
{
processGetCom(input);
}
else if (input[0].compare("record") == 0)
{
processRecordCom(input);
}
else if (input[0].compare("remove") == 0)
{
processRemoveCom(input);
}
else if (input[0].compare("add") == 0)
{
processAddCom(input);
}
else if (input[0].compare("exit") == 0)
{
exit(0);
}
}
}
/* Updated C. A. Acred on 05/22/2015
* This method takes a string and splits it into a vector with the second input.
*/
vector<string> splitString(string input, string splitter)
{
vector<string> output; // initialize output vector
int currentElement = 0; // set current vector element to 0
string currentChar; // declare a container for the current char
output.push_back(""); // Push an empty string onto output
for(int i = 0; i < input.length(); i++) // for each char in input
{
currentChar = input.substr(i, 1); // currentChar = the char in input # i
if (currentChar.compare(splitter) == 0) // if this char and the splitter are the same
{
while (currentChar.compare(splitter) == 0) // while they are the same
{
i++; // advance i by 1
currentChar = input.substr(i, 1); // get the next char
}
output.push_back(currentChar); // put the current char as the first in a new element
currentElement++; // point to the new element
}
else
{
output[currentElement] = output[currentElement] + currentChar; // output # currentElement += currentChar
}
}
return output;
}
string requiredExercises()
{
return "yo";
}
/* Updated C. A. Acred on 5/27/15
* Processes get commands.
*/
void processGetCom(vector<string> input)
{
if (input.size() > 2)
{
printError("To many arguments; Enter a valid command");
}
if (input[1].compare("required") == 0)
{
cout << requiredExercises();
}
else
{
cout << getRecord(input[1]);
}
}
void processRecordCom(vector<string> input)
{
}
void processRemoveCom(vector<string> input)
{
}
void processAddCom(vector<string> input)
{
}
void printError(string reason)
{
}
/** Updated C. A. Acred 05/22/2015
* Print help on commands.
*/
void help(string context)
{
if (context.empty())
{
int i;
for (i = 0; i < commandHelpGet.size(); i++)
{
cout << commandHelpGet[i];
}
for (i = 0; i < commandHelpRec.size(); i++)
{
cout << commandHelpRec[i];
}
for (i = 0; i < commandHelpRem.size(); i++)
{
cout << commandHelpRem[i];
}
for (i = 0; i < commandHelpAdd.size(); i++)
{
cout << commandHelpAdd[i];
}
}
cout << instructionSpace + "To exit type:: exit\n";
cout << instructionSpace + "-+| date format = m/d/yr |+-\n\t\tExample:: 05/20/2015\n";
cout << instructionSpace + "-+| daysOFWeek format = day/day/day..etc(up to 7) |+-\n\t\tExample:: mon/tue/wed/thur/fri/sat/sun\n\n\n\n";
cout << instructionSpace + "-+| rep format = rep:(#) |+-\n\t\tExample:: rep:15\n\n\n\n";
cout << instructionSpace + "-+| min format = min:(#) |+-\n\t\tExample:: min:15\n\n\n\n";
}
And here is the strange error I am getting from g++:
main.cpp:24:84: error: invalid conversion from 'const char*' to 'unsigned int' [-fpermissive]
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_vector.h:263:7: error: initializing argument 1 of 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = std::basic_string<char>, _Alloc = std::allocator<std::basic_stri
ng<char> >, std::vector<_Tp, _Alloc>::size_type = unsigned int, std::vector<_Tp, _Alloc>::value_type = std::basic_string<char>, std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::basic_string<char> >]' [-fpermissive]
main.cpp:25:111: error: invalid conversion from 'const char*' to 'unsigned int' [-fpermissive]
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_vector.h:263:7: error: initializing argument 1 of 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = std::basic_string<char>, _Alloc = std::allocator<std::basic_stri
ng<char> >, std::vector<_Tp, _Alloc>::size_type = unsigned int, std::vector<_Tp, _Alloc>::value_type = std::basic_string<char>, std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::basic_string<char> >]' [-fpermissive]
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/vector:63:0,
from main.cpp:10:
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_construct.h: In function 'void std::_Construct(_T1*, const _T2&) [with _T1 = std::basic_string<char>, _T2 = char]':
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_uninitialized.h:77:3: instantiated from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const char*, _ForwardIterator = std::bas
ic_string<char>*, bool _TrivialValueTypes = false]'
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_uninitialized.h:119:41: instantiated from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const char*, _ForwardIterator = std::basic_string<char>*]'
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_uninitialized.h:259:63: instantiated from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = const char*, _ForwardIterator = std::basic_string<char>*
, _Tp = std::basic_string<char>]'
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_vector.h:1113:4: instantiated from 'void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const char*, _Tp = std::basic_string<char>, _Alloc = std::alloca
tor<std::basic_string<char> >]'
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_vector.h:1091:4: instantiated from 'void std::vector<_Tp, _Alloc>::_M_initialize_dispatch(_InputIterator, _InputIterator, std::__false_type) [with _InputIterator = const char*, _Tp = std::basic_string<char>, _Alloc = std::allocator<std::ba
sic_string<char> >]'
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_vector.h:340:4: instantiated from 'std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&) [with _InputIterator = const char*, _Tp = std::basic_string<char>, _Alloc = std::allocator<std::basic_string<char> >
, std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::basic_string<char> >]'
main.cpp:22:140: instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_construct.h:84:7: error: invalid conversion from 'char' to 'const char*' [-fpermissive]
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/basic_string.tcc:214:5: error: initializing argument 1 of 'std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]' [-fpermiss
ive]
Any help with understanding and fixing this error is most appreciated.
UPDATE #1:
I changed the initialization of the vectors commandHelpGet - commandHelpAdd to use curly braces, but now I get a new error:
main.cpp:22:16: warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x [enabled by default]
main.cpp:22:139: error: in C++98 'commandHelpGet' must be initialized by constructor, not by '{...}'
main.cpp:23:16: warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x [enabled by default]
main.cpp:23:147: error: in C++98 'commandHelpRem' must be initialized by constructor, not by '{...}'
main.cpp:24:16: warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x [enabled by default]
main.cpp:24:84: error: in C++98 'commandHelpRec' must be initialized by constructor, not by '{...}'
main.cpp:24:84: error: invalid conversion from 'const char*' to 'unsigned int' [-fpermissive]
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_vector.h:263:7: error: initializing argument 1 of 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = std::basic_string<char>, _Alloc = std::allocator<std::basic_stri
ng<char> >, std::vector<_Tp, _Alloc>::size_type = unsigned int, std::vector<_Tp, _Alloc>::value_type = std::basic_string<char>, std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::basic_string<char> >]' [-fpermissive]
main.cpp:25:16: warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x [enabled by default]
main.cpp:25:111: error: in C++98 'commandHelpAdd' must be initialized by constructor, not by '{...}'
main.cpp:25:111: error: invalid conversion from 'const char*' to 'unsigned int' [-fpermissive]
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_vector.h:263:7: error: initializing argument 1 of 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = std::basic_string<char>, _Alloc = std::allocator<std::basic_stri
ng<char> >, std::vector<_Tp, _Alloc>::size_type = unsigned int, std::vector<_Tp, _Alloc>::value_type = std::basic_string<char>, std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::basic_string<char> >]' [-fpermissive]
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/vector:63:0,
from main.cpp:10:
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_construct.h: In function 'void std::_Construct(_T1*, const _T2&) [with _T1 = std::basic_string<char>, _T2 = char]':
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_uninitialized.h:77:3: instantiated from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const char*, _ForwardIterator = std::bas
ic_string<char>*, bool _TrivialValueTypes = false]'
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_uninitialized.h:119:41: instantiated from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const char*, _ForwardIterator = std::basic_string<char>*]'
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_uninitialized.h:259:63: instantiated from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = const char*, _ForwardIterator = std::basic_string<char>*
, _Tp = std::basic_string<char>]'
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_vector.h:1113:4: instantiated from 'void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const char*, _Tp = std::basic_string<char>, _Alloc = std::alloca
tor<std::basic_string<char> >]'
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_vector.h:1091:4: instantiated from 'void std::vector<_Tp, _Alloc>::_M_initialize_dispatch(_InputIterator, _InputIterator, std::__false_type) [with _InputIterator = const char*, _Tp = std::basic_string<char>, _Alloc = std::allocator<std::ba
sic_string<char> >]'
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_vector.h:340:4: instantiated from 'std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&) [with _InputIterator = const char*, _Tp = std::basic_string<char>, _Alloc = std::allocator<std::basic_string<char> >
, std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::basic_string<char> >]'
main.cpp:22:139: instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_construct.h:84:7: error: invalid conversion from 'char' to 'const char*' [-fpermissive]
c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/basic_string.tcc:214:5: error: initializing argument 1 of 'std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]' [-fpermiss
ive]
- CAA14
Take a look at your vector initializations. If your intention is to use list syntax, then use braces instead of parens:
vector<string> commandHelpGet { "To view a day's exercises type:: get (date)\n", "To view today's required exercises type:: get required\n" };
Look at the examples here.
I'm trying to read from a const std::vector to an std::istream, but everything I've tried runs into the problem with const.
This version compiles perfectly:
#include <vector>
#include <iostream>
template<typename CharT = char, typename TraitsT = std::char_traits<CharT> >
class vectorbuf : public std::basic_streambuf<CharT, TraitsT> {
public:
vectorbuf(std::vector<char>& v) {
this->setg(v.data(), v.data(), v.data()+v.size());
}
};
void doStuff(std::vector<char>& v) {
vectorbuf<> vbuff(v);
std::istream s(&vbuff);
}
int main(int argc, char** argv) {
std::vector<char> v = {'a', 'b', 'c'};
doStuff(v);
return 0;
}
while this produces errors:
#include <vector>
#include <iostream>
template<typename CharT = char, typename TraitsT = std::char_traits<CharT> >
class const_vectorbuf : public std::basic_streambuf<CharT, TraitsT> {
public:
const_vectorbuf(const std::vector<char>& v) {
this->setg(v.data(), v.data(), v.data()+v.size());
}
};
void const_doStuff(const std::vector<char>& v) {
const_vectorbuf<const char> vbuff(v);
//std::istream s(&vbuff); With this commented out I get the error below
}
int main(int argc, char** argv) {
std::vector<char> v = {'a', 'b', 'c'};
const_doStuff(v);
return 0;
}
And I'm not sure how to fix it.
The error:
In file included from /usr/include/c++/4.8/ios:40:0,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from vector_stream.cpp:2:
/usr/include/c++/4.8/bits/char_traits.h: In instantiation of ‘static void __gnu_cxx::char_traits<_CharT>::assign(__gnu_cxx::char_traits<_CharT>::char_type&, const char_type&) [with _CharT = const char; __gnu_cxx::char_traits<_CharT>::char_type = const char]’:
/usr/include/c++/4.8/bits/streambuf.tcc:67:63: required from ‘std::streamsize std::basic_streambuf<_CharT, _Traits>::xsgetn(std::basic_streambuf<_CharT, _Traits>::char_type*, std::streamsize) [with _CharT = const char; _Traits = std::char_traits<const char>; std::streamsize = long int; std::basic_streambuf<_CharT, _Traits>::char_type = const char]’
vector_stream.cpp:36:1: required from here
/usr/include/c++/4.8/bits/char_traits.h:93:14: error: assignment of read-only reference ‘__c1’
{ __c1 = __c2; }
^
In file included from /usr/include/c++/4.8/vector:60:0,
from vector_stream.cpp:1:
/usr/include/c++/4.8/bits/stl_algobase.h: In instantiation of ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = const char*; _OI = const char*]’:
/usr/include/c++/4.8/bits/stl_algobase.h:428:38: required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = const char*; _OI = const char*]’
/usr/include/c++/4.8/bits/stl_algobase.h:460:17: required from ‘_OI std::copy(_II, _II, _OI) [with _II = const char*; _OI = const char*]’
/usr/include/c++/4.8/bits/char_traits.h:192:39: required from ‘static __gnu_cxx::char_traits<_CharT>::char_type* __gnu_cxx::char_traits<_CharT>::copy(__gnu_cxx::char_traits<_CharT>::char_type*, const char_type*, std::size_t) [with _CharT = const char; __gnu_cxx::char_traits<_CharT>::char_type = const char; std::size_t = long unsigned int]’
/usr/include/c++/4.8/bits/streambuf.tcc:56:50: required from ‘std::streamsize std::basic_streambuf<_CharT, _Traits>::xsgetn(std::basic_streambuf<_CharT, _Traits>::char_type*, std::streamsize) [with _CharT = const char; _Traits = std::char_traits<const char>; std::streamsize = long int; std::basic_streambuf<_CharT, _Traits>::char_type = const char]’
vector_stream.cpp:36:1: required from here
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: error: no matching function for call to ‘std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m(const char*&, const char*&, const char*&)’
_Category>::__copy_m(__first, __last, __result);
^
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: note: candidate is:
/usr/include/c++/4.8/bits/stl_algobase.h:368:9: note: template<class _Tp> static _Tp* std::__copy_move<_IsMove, true, std::random_access_iterator_tag>::__copy_m(const _Tp*, const _Tp*, _Tp*) [with _Tp = _Tp; bool _IsMove = false]
__copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result)
^
/usr/include/c++/4.8/bits/stl_algobase.h:368:9: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: note: deduced conflicting types for parameter ‘_Tp’ (‘char’ and ‘const char’)
_Category>::__copy_m(__first, __last, __result);
So despite CharT being const char streambuf_type is still char, I've been looking and so far I haven't found a way to change that. The assignment __c1 = __c2 in char_traits I haven't had the time to even begin look at a way to solve yet.
I feel quite certain that basic_streambuf requires it's first template to be not-const. Also, I think basic_streambuf requires write access, because the basic_streambuf manages both in and out, regardless of what you use it for in the end. You should probably also override some other members to cause writes to fail: sputbackc, sungetc, sputc, sputn, xsputn...
§ 27.2.2/2 In the classes of Clause 27, a template formal parameter with name charT represents a member of the set of types containing char, wchar_t, and any other implementation-defined character types that satisfy the requirements for a character on which any of the iostream components can be instantiated.
(emphsis mine) This rule is a little vague, but I'm pretty sure it clearly covers your case.
I have very simple and stupid trouble:
std::map<b2Vec2, b2Body*> mTakePoints;
mTakePoints.insert(std::make_pair(point, body));
Compiler says:
In file included from /usr/include/c++/4.4/string:50,
from /usr/include/ClanLib-2.2/ClanLib/Display/../Core/Text/string_types.h:34,
from /usr/include/ClanLib-2.2/ClanLib/Display/display.h:35,
from /usr/include/ClanLib-2.2/ClanLib/display.h:40,
from /home/pfight/Themisto/include/World/Actions/Action.hpp:21,
from /home/pfight/Themisto/include/World/Actions/TakeAction.hpp:21,
from /home/pfight/Themisto/src/World/Actions/TakeAction.cpp:18:
/usr/include/c++/4.4/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = b2Vec2]’:
/usr/include/c++/4.4/bits/stl_tree.h:1170: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = b2Vec2, _Val = std::pair<const b2Vec2, b2Body*>, _KeyOfValue = std::_Select1st<std::pair<const b2Vec2, b2Body*> >, _Compare = std::less<b2Vec2>, _Alloc = std::allocator<std::pair<const b2Vec2, b2Body*> >]’
/usr/include/c++/4.4/bits/stl_map.h:500: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [with _Key = b2Vec2, _Tp = b2Body*, _Compare = std::less<b2Vec2>, _Alloc = std::allocator<std::pair<const b2Vec2, b2Body*> >]’
/home/pfight/Themisto/src/World/Actions/TakeAction.cpp:43: instantiated from here
/usr/include/c++/4.4/bits/stl_function.h:230: error: no match for ‘operator<’ in ‘__x < __y’
/usr/include/ClanLib-2.2/ClanLib/Display/../Core/Text/string_data16.h:383: note: candidates are: bool operator<(const CL_StringData16&, const wchar_t*)
/usr/include/ClanLib-2.2/ClanLib/Display/../Core/Text/string_data16.h:382: note: bool operator<(const wchar_t*, const CL_StringData16&)
/usr/include/ClanLib-2.2/ClanLib/Display/../Core/Text/string_data16.h:381: note: bool operator<(const CL_StringData16&, const CL_StringData16&)
/usr/include/ClanLib-2.2/ClanLib/Display/../Core/Text/string_data8.h:383: note: bool operator<(const CL_StringData8&, const char*)
/usr/include/ClanLib-2.2/ClanLib/Display/../Core/Text/string_data8.h:382: note: bool operator<(const char*, const CL_StringData8&)
/usr/include/ClanLib-2.2/ClanLib/Display/../Core/Text/string_data8.h:381: note: bool operator<(const CL_StringData8&, const CL_StringData8&)
TakeAction.cpp:43 it is row with insert call. For fun I tried next:
std::pair<b2Vec2, b2Body*> item(point, body);
mTakePoints.insert(item);
All the same.
I'm pretty confused, explain please, what is wrong?
Did you define the following operator:?
bool operator< (const b2Vec2&, const b2Vec2&)
std::map requires that the less-than operator be defined for keys, or that a less-than operator be provided as a template argument. In particular, std::map is implemented as a (sorted) binary tree, and needs operator< to figure out where to put new items.
For map, set and the like ordered containers must be told where to put new items. This is done by implementing the less-than operator:
bool operator< (const b2Vec2& first, const b2Vec2& second)
{
return first.some_attribute < second.some_attribute;
}
You can see in the compilation error that it was missing:
/usr/include/c++/4.4/bits/stl_function.h:230: error: no match for ‘operator<’ in ‘__x < __y’
The rest of the output tells you that the compiler tried to find a suitable operator and failed.