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 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.
When creating my own allocator in c++11 I am implementing the following interfaces. This works with vector but when trying to use this with map I get errors on missing items. I thought this was all I need to implement for c++11 since it will use allocator_traits in the stl implementations. What am I missing here? Do I need to define more methods / data structures for an allocator for std::map? I am seeing the following errors when trying to compile currently (see below). Line 3 main.cpp is just
#include <map>
template <class T> struct MyAllocator {
typedef T value_type;
MyAllocator() noexcept; // only required if used
MyAllocator(const MyAllocator&) noexcept; // copies must be equal
MyAllocator(MyAllocator&&) noexcept; // not needed if copy ctor is good enough
template <class U> MyAllocator(const MyAllocator<U>& u) noexcept;
// requires: *this == MyAllocator(u)
value_type* allocate(std::size_t);
void deallocate(value_type*, std::size_t) noexcept;
};
template <class T, class U> bool
operator==(const MyAllocator<T>&, const MyAllocator<U>&) noexcept;
Errors:
In file included from
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/map:61:0,
from main.cpp:3:
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h: In
instantiation of ‘class std::map,
MyAlloc >’:
main.cpp:146:14: required from here
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h:143:58:
error: no type named ‘pointer’ in ‘std::map,
MyAlloc >::_Pair_alloc_type {aka class
MyAlloc, 200 typedef typename
_Pair_alloc_type::pointer pointer; ^
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h:144:58:
error: no type named ‘const_pointer’ in ‘std::map, MyAlloc >::_Pair_alloc_type {aka class
MyAlloc
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h:145:58:
error: no type named ‘reference’ in ‘std::map, MyAlloc >::_Pair_alloc_type {aka class
MyAlloc, 2 typedef typename
_Pair_alloc_type::reference reference; ^
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h:146:58:
error: no type named ‘const_reference’ in ‘std::map, MyAlloc >::_Pair_alloc_type {aka class
MyAlloc
In file included from
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/map:60:0,
from main.cpp:3:
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_tree.h: In
instantiation of ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue,
_Compare, _Alloc>::_M_destroy_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_t /opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_tree.h:1124:23:
required from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare,
_Alloc>::_M_erase(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type /opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_tree.h:671:28:
required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare,
_Alloc>::~_Rb_tree() [with _Key = int; _Val = std::pair; _KeyOfValue = std::
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_map.h:96:11:
required from here
/opt/gcc-4.8.1/usr/local/include/c++/4.8.1/bits/stl_tree.h:421:2:
error: ‘std::_Rb_tree,
std::_Select1st >, std::less,
MyAlloc, 200ul> >:
_M_get_Node_allocator().destroy(__p); ^
make: *** [main.o] Error 1
The first errors are solved using some typedefs within MyAllocator:
typedef T& reference;
typedef const T& const_reference;
typedef T* pointer;
typedef const T* const_pointer;
Please post your new compilation output.
Basically as my comment suggested I needed to put the typedefs for the following and a construct and destroy
template <class U>
struct rebind {typedef MyAlloc<U, N> other;};
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
/// Call constructor with many arguments
template<typename U, typename... Args>
void construct(U* p, Args&&... args)
{
// Placement new
::new((void *)p) U(std::forward<Args>(args)...);
}
/// Call destructor
template<typename U>
void destroy(U* p)
{
p->~U();
}
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.