Explicitly Asking for Default Move Constructor Does not Work? - c++11

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.

Related

Why do I need the move constructor, if the constructor take values

I have the following example:
#include <cstdint>
class A
{
public:
A(const A&) = delete;
A& operator = (const A&) = delete;
A(A&&) = default; // why do I need the move constructor
A&& operator = (A&&) = delete;
explicit A(uint8_t Val)
{
_val = Val;
}
virtual ~A() = default;
private:
uint8_t _val = 0U;
};
class B
{
public:
B(const B&) = delete;
B& operator = (const B&) = delete;
B(B&&) = delete;
B&& operator = (B&&) = delete;
B() = default;
virtual ~B() = default;
private:
A _a = A(4U); // call the overloaded constructor of class A
};
int main()
{
B b;
return 0;
}
why do I need the move-constructor "A(A&&) = default;" in A? I could not the code line where the mentioned move-constructor is called.
Many thanks in advance.
A _a = A(4U) in this case depends on the move constructor.
This type of initialization is called copy initialization, and according to the standard it may invoke the move constructor, see 9.3/14.

C++: Error retrieving STL map from another map

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.

Strange gdb c++ error

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.

Reading from const std::vector<char> via std::istream

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.

unable to find what causes a compile time error

I'm using MinGW 4.8.0 (included in QtCreator 5.1) with C++11.
The problem is that I get a compile time error but I can not find the source of the error.
typedef std::unique_ptr< ADMessageReqRSSingle > MsgType;
typedef std::vector< MsgType > Cont;
typedef Cont::const_iterator MsgCIter;
Cont mCont; // Inside another clas
Is there a diagnostic tool that is a little more specific?
The gcc log is the following:
Makefile.Debug:1491: recipe for target 'debug/adsync.o' failed
In file included from c:\qt\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\memory:64:0,
from ..\aams/iocontroller/iocontroller.hpp:15,
from ..\aams/aams/aamscontext.h:13,
from ..\aams\src\aams\adsync.cpp:8:
c:\qt\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::unique_ptr<aams::device::ADMessageReqRSSingle>; _Args = {const std::unique_ptr<aams::device::ADMessageReqRSSingle, std::default_delete<aams::device::ADMessageReqRSSingle> >&}]':
c:\qt\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_uninitialized.h:75:53: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<aams::device::ADMessageReqRSSingle>*, std::vector<std::unique_ptr<aams::device::ADMessageReqRSSingle> > >; _ForwardIterator = std::unique_ptr<aams::device::ADMessageReqRSSingle>*; bool _TrivialValueTypes = false]'
c:\qt\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_uninitialized.h:117:41: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<aams::device::ADMessageReqRSSingle>*, std::vector<std::unique_ptr<aams::device::ADMessageReqRSSingle> > >; _ForwardIterator = std::unique_ptr<aams::device::ADMessageReqRSSingle>*]'
c:\qt\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_uninitialized.h:258:63: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<aams::device::ADMessageReqRSSingle>*, std::vector<std::unique_ptr<aams::device::ADMessageReqRSSingle> > >; _ForwardIterator = std::unique_ptr<aams::device::ADMessageReqRSSingle>*; _Tp = std::unique_ptr<aams::device::ADMessageReqRSSingle>]'
c:\qt\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_vector.h:316:32: required from 'std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::unique_ptr<aams::device::ADMessageReqRSSingle>; _Alloc = std::allocator<std::unique_ptr<aams::device::ADMessageReqRSSingle> >]'
..\aams/aams/device/admessagereq.h:687:50: required from here
c:\qt\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_construct.h:75:7: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = aams::device::ADMessageReqRSSingle; _Dp = std::default_delete<aams::device::ADMessageReqRSSingle>]'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
In file included from c:\qt\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\memory:81:0,
from ..\aams/iocontroller/iocontroller.hpp:15,
from ..\aams/aams/aamscontext.h:13,
from ..\aams\src\aams\adsync.cpp:8:
c:\qt\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\unique_ptr.h:273:7: error: declared here
unique_ptr(const unique_ptr&) = delete;
^
Based on the errors and on your answer to my comment:
You can't have container with unique_ptr as it's not copy-constructable, which is necessary for all STL containers.
You have something like:
class A
{
public:
A() {}
private:
std::vector<std::unique_ptr<int>> ints;
};
So, A is not copyable (because unique_ptr is not),
To have better error message, you may add explicitly
A(const A&) = delete;
A& operator = (const A&) = delete;
Following code shows your error message.
int main() {
A a, b;
a = b; // Error appears due to this copy
return 0;
}
You may use move instead of copy if appropriate.
int main() {
A a, b;
a = std::move(b); // No error, but b is now "invalid"
return 0;
}
EDIT: Just see your comment about Clone in comment in another answer:
Clone is a copy (and A is not copyable so an error).
you may use (if appropriate) something like:
std::unique_ptr<A> A::Clone() const {
std::unique_ptr<A> res(new A());
for (auto i : ints) {
// copy the value, not the pointer.
res->ints.push_back(std::unique_ptr<int>(new int(*i)));
}
return res;
}
Items in a vector must be assignable (or, in more recent versions of the standard, movable).
See the answer of Jerry Coffin
You compiler does not seem to be recent enough to accept the moveable part.
Another possible reason anyone might get this error if you made a vector of const objects which are also not assignable.

Resources