ranges views size does not compile - c++

#include <iostream>
#include <cstdlib>
#include <vector>
#include <ranges>
#include <algorithm>
using namespace std;
int main()
{
vector<int> ints = {1,2,3,4,5};
auto v = ints | views::take_while([](int i){return i<3;}) ;
for (int i : v) std::cout << i << ' ';
std::cout << '\n';
int size = v.size();
std::cout << size << std::endl;
}
v.size() does not compile. How do you do this ?
prog.cc: In function 'int main()':
prog.cc:16:23: error: no matching function for call to 'std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >::size()'
16 | int size = v.size();
| ^
In file included from prog.cc:5:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:144:7: note: candidate: 'constexpr auto std::ranges::view_interface<_Derived>::size() requires (forward_range<_Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<_Tp&>)())), decltype(std::__detail::__ranges_begin((declval<_Container&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]'
144 | size()
| ^~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:144:7: note: constraints not satisfied
In file included from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_iterator_base_types.h:71,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_algobase.h:65,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/char_traits.h:39,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ios:40,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ostream:38,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/iostream:39,
from prog.cc:2:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h: In instantiation of 'constexpr auto std::ranges::view_interface<_Derived>::size() requires (forward_range<_Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<_Tp&>)())), decltype(std::__detail::__ranges_begin((declval<_Container&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]':
prog.cc:16:23: required from here
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:555:13: required for the satisfaction of 'sized_sentinel_for<std::ranges::sentinel_t<_Tp>, decltype (std::__detail::__ranges_begin(declval<_Container&>()))>' [with _Tp = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>; _Container = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:557:8: in requirements with 'const _Iter& __i', 'const _Sent& __s' [with _Arg = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >; _Sent = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>::_Sentinel<true>; _Iter = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:559:13: note: the required expression '(__s - __i)' is invalid
559 | { __s - __i } -> same_as<iter_difference_t<_Iter>>;
| ~~~~^~~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:560:13: note: the required expression '(__i - __s)' is invalid
560 | { __i - __s } -> same_as<iter_difference_t<_Iter>>;
| ~~~~^~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
In file included from prog.cc:5:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:150:7: note: candidate: 'constexpr auto std::ranges::view_interface<_Derived>::size() const requires (forward_range<const _Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<const _Range&>)())), decltype(std::__detail::__ranges_begin((declval<const _Range&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]'
150 | size() const
| ^~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:150:7: note: constraints not satisfied
In file included from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_iterator_base_types.h:71,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_algobase.h:65,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/char_traits.h:39,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ios:40,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ostream:38,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/iostream:39,
from prog.cc:2:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h: In instantiation of 'constexpr auto std::ranges::view_interface<_Derived>::size() const requires (forward_range<const _Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<const _Range&>)())), decltype(std::__detail::__ranges_begin((declval<const _Range&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]':
prog.cc:16:23: required from here
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:555:13: required for the satisfaction of 'sized_sentinel_for<std::ranges::sentinel_t<const _Range>, decltype (std::__detail::__ranges_begin(declval<const _Range&>()))>' [with _Range = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:557:8: in requirements with 'const _Iter& __i', 'const _Sent& __s' [with _Arg = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >; _Sent = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>::_Sentinel<true>; _Iter = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:559:13: note: the required expression '(__s - __i)' is invalid
559 | { __s - __i } -> same_as<iter_difference_t<_Iter>>;
| ~~~~^~~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:560:13: note: the required expression '(__i - __s)' is invalid
560 | { __i - __s } -> same_as<iter_difference_t<_Iter>>;
| ~~~~^~~~~

Since take_while and its ilk shorten the size of the list in unpredictable ways, those range adaptors cannot return a sized_range, even if the input itself is sized. sized_range requires that the range can compute the size in O(1) time, and take_while's view cannot do that.
So if you want the size (and you shouldn't), you will have to compute it yourself. You could also use std::ranges::distance on the range.

Related

C++ std::thread arguments must be invocable after conversion to rvalues

I'm clueless on whats going on here
here is a simple code example of what I'm trying to achieve:
main.cpp
#include <iostream>
#include <thread>
int main(int argc, char** argv) {
constexpr int SIZE = 10;
std::array<int, SIZE> arr{0};
auto add = []<typename T>(std::array<T, SIZE>& arr) {
for (int i = 0; i < SIZE; i++)
arr[i] = i + 1;
};
std::thread t1(std::ref(add), std::ref(arr));
t1.join();
return 0;
}
compile command:
g++ -std=c++20 -Wall main.cpp -pthread -o t1
error:
In file included from /usr/include/c++/11.1.0/stop_token:35,
from /usr/include/c++/11.1.0/thread:40,
from main.cpp:2:
/usr/include/c++/11.1.0/bits/std_thread.h: In instantiation of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >; _Args = {std::reference_wrapper<std::array<int, 10> >}; <template-parameter-1-3> = void]’:
main.cpp:15:48: required from here
/usr/include/c++/11.1.0/bits/std_thread.h:130:72: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
130 | typename decay<_Args>::type...>::value,
| ^~~~~
/usr/include/c++/11.1.0/bits/std_thread.h:130:72: note: ‘std::integral_constant<bool, false>::value’ evaluates to false
/usr/include/c++/11.1.0/bits/std_thread.h: In instantiation of ‘struct std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >’:
/usr/include/c++/11.1.0/bits/std_thread.h:203:13: required from ‘struct std::thread::_State_impl<std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > > >’
/usr/include/c++/11.1.0/bits/std_thread.h:143:29: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >; _Args = {std::reference_wrapper<std::array<int, 10> >}; <template-parameter-1-3> = void]’
main.cpp:15:48: required from here
/usr/include/c++/11.1.0/bits/std_thread.h:252:11: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >::__result<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >’
252 | _M_invoke(_Index_tuple<_Ind...>)
| ^~~~~~~~~
/usr/include/c++/11.1.0/bits/std_thread.h:256:9: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >::__result<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >’
256 | operator()()
| ^~~~~~~~
note:
if I change the lambda to:
auto add = []<typename T>(std::array<T, SIZE> arr)
and call the thread like this:
std::thread t1(std::ref(add), arr);
it compiles, but obviously the array doesn't changed because its a copy and not a reference
std::reference_wrapper is not a std::array, so T cannot be deduced.
add(std::ref(arr)); doesn't compile neither.
You might use
std::thread t1([&](auto arg){ add(arg.get()); }, std::ref(arr));
Demo

i want to implement map in c++ , for that i can't check vector size and give values to vector i made

i made two classes Node and Map , when i try to get table_size in Map Constructor and want assign all vector values as nullptr it gives me error.
my code is here it's not a problem by overloaded operator i commented it , i still get error
#include <iostream>
#include <vector>
template <class T1,class T2>
class Node {
public:
T1 key;
T2 value;
Node* next;
Node(T1 key,T2 value) : key(key) , value(value) , next(nullptr) {};
};
template <class T1,class T2>
class Map {
private:
std::vector<Node<T1,T2>*> hash_table[117];
int table_size;
public:
Map() {
table_size = hash_table.size();
for(int i=0;i<table_size;i++) {
hash_table[i] = nullptr;
}
}
// i assumed that T1 is always string
int stringToHash(T1 key) {
int num = 0;
for(int i=0;i<key.length();i++) {
num += int(key[i]);
}
return ( ( num * 1027 ) % table_size );
}
void put(T1 key,T2 value) {
int idx = stringToHash(key);
Node<T1,T2>* new_node = createNode(key,value);
if(hash_table[idx] == nullptr)
hash_table[idx] = new_node;
else {
Node<T1,T2>* ptr = hash_table[idx];
while(ptr->next != nullptr) {
ptr = ptr->next;
}
ptr->next = new_node;
}
}
T2 operator[] (T1 key) {
int idx = stringToHash(key);
Node<T1,T2>* ptr = hash_table[idx];
T2 value;
while(ptr != nullptr) {
if(ptr->key == key) {
value = ptr->value;
}
ptr = ptr->next;
}
return value;
}
Node<T1,T2>* createNode(T1 key,T2 value) {
Node<T1,T2>* new_node = new Node<T1,T2>(key,value);
return new_node;
}
};
int main() {
Map<std::string,std::string> arr;
return 0;
}
my error follows as
03_map.cpp: In instantiation of ‘Map<T1, T2>::Map() [with T1 = std::__cxx11::basic_string<char>; T2 = std::__cxx11::basic_string<char>]’:
03_map.cpp:74:34: required from here
03_map.cpp:21:37: error: request for member ‘size’ in ‘((Map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*)this)->Map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::hash_table’, which is of non-class type ‘std::vector<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*, std::allocator<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*> > [117]’
21 | table_size = hash_table.size();
| ~~~~~~~~~~~^~~~
03_map.cpp:23:31: error: no match for ‘operator=’ (operand types are ‘std::vector<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*, std::allocator<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*> >’ and ‘std::nullptr_t’)
23 | hash_table[i] = nullptr;
| ~~~~~~~~~~~~~~^~~~~~~~~
In file included from /usr/include/c++/10.2.0/vector:72,
from 03_map.cpp:2:
/usr/include/c++/10.2.0/bits/vector.tcc:198:5: note: candidate: ‘std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(const std::vector<_Tp, _Alloc>&) [with _Tp = Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*; _Alloc = std::allocator<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*>]’
198 | vector<_Tp, _Alloc>::
| ^~~~~~~~~~~~~~~~~~~
/usr/include/c++/10.2.0/bits/vector.tcc:199:42: note: no known conversion for argument 1 from ‘std::nullptr_t’ to ‘const std::vector<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*, std::allocator<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*> >&’
199 | operator=(const vector<_Tp, _Alloc>& __x)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
In file included from /usr/include/c++/10.2.0/vector:67,
from 03_map.cpp:2:
/usr/include/c++/10.2.0/bits/stl_vector.h:709:7: note: candidate: ‘std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(std::vector<_Tp, _Alloc>&&) [with _Tp = Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*; _Alloc = std::allocator<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*>]’
709 | operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
| ^~~~~~~~
/usr/include/c++/10.2.0/bits/stl_vector.h:709:26: note: no known conversion for argument 1 from ‘std::nullptr_t’ to ‘std::vector<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*, std::allocator<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*> >&&’
709 | operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
| ~~~~~~~~~^~~
/usr/include/c++/10.2.0/bits/stl_vector.h:730:7: note: candidate: ‘std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(std::initializer_list<_Tp>) [with _Tp = Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*; _Alloc = std::allocator<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*>]’
730 | operator=(initializer_list<value_type> __l)
| ^~~~~~~~
/usr/include/c++/10.2.0/bits/stl_vector.h:730:46: note: no known conversion for argument 1 from ‘std::nullptr_t’ to ‘std::initializer_list<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*>’
730 | operator=(initializer_list<value_type> __l)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
can you tell me what did i done wrong ?
This:
std::vector<Node<T1,T2>*> hash_table[117];
Is not a vector. It's an array of 117 vectors. Arrays don't have a size() member.
Your hash_table (std::vector<Node<T1,T2>*> hash_table[117];) is a c style array, and does not have a method size as of that table_size = hash_table.size(); results in the error:
error: request for member ‘size’ in ‘((Map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*)this)->Map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::hash_table’, which is of non-class type ‘std::vector<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*, std::allocator<Node<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >*> > [117]’
21 | table_size = hash_table.size();
And hash_table[i] = nullptr; won't work because hash_table[i] refers to an instance of std::vector and can't be nullptr
Instead of std::vector<Node<T1,T2>*> hash_table[117]; you most likely want to have std::array<Node<T1,T2>*, 117> hash_table; or if you want to have a std::vector to be able to resize it you would use std::vector<Node<T1,T2>*> hash_table = std::vector<Node<T1,T2>*>(117);

Taking 2D vector out of 3D Vector and replace with other 2D-Vector

I want to save for an game my 2D-Vector std::vector<std::vector<std::string>> _map in an 3D-Vector std::vector<std::vector<std::vector<std::string>>> _save with:
_save.push_back(_map);
Later I want (if condition) replace my 2D-Vector by the last-saved 2D-Vector in my 3D-Vector and then delete the last-saved 2D-Vector. My code is:
std::vector<std::vector<std::string>> map2;
int var = _save.size() -1; // tried with _save.back() too
map2.push_back(_save[var]);
_save.pop_back();
_map.swap(map2);
What am I doing wrong? What should it look like? Thank you for your help.
Following error:
Structure.cpp: In member function ‘void Structure::undo(bool)’:
Structure.cpp:69:30: error: no matching function for call to ‘std::vector<std::vector<std::basic_string<char> > >::push_back(__gnu_cxx::__alloc_traits<std::allocator<std::vector<std::vector<std::basic_string<char> > > > >::value_type&)’
map2.push_back(_save[var]);
^
Structure.cpp:69:30: note: candidates are:
In file included from /usr/include/c++/4.9/vector:64:0,
from Structure.cpp:6:
/usr/include/c++/4.9/bits/stl_vector.h:913:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::vector<std::basic_string<char> >; _Alloc = std::allocator<std::vector<std::basic_string<char> > >; std::vector<_Tp, _Alloc>::value_type = std::vector<std::basic_string<char> >]
push_back(const value_type& __x)
^
/usr/include/c++/4.9/bits/stl_vector.h:913:7: note: no known conversion for argument 1 from ‘__gnu_cxx::__alloc_traits<std::allocator<std::vector<std::vector<std::basic_string<char> > > > >::value_type {aka std::vector<std::vector<std::basic_string<char> > >}’ to ‘const value_type& {aka const std::vector<std::basic_string<char> >&}’
/usr/include/c++/4.9/bits/stl_vector.h:931:7: note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::vector<std::basic_string<char> >; _Alloc = std::allocator<std::vector<std::basic_string<char> > >; std::vector<_Tp, _Alloc>::value_type = std::vector<std::basic_string<char> >]
push_back(value_type&& __x)
^
/usr/include/c++/4.9/bits/stl_vector.h:931:7: note: no known conversion for argument 1 from ‘__gnu_cxx::__alloc_traits<std::allocator<std::vector<std::vector<std::basic_string<char> > > > >::value_type {aka std::vector<std::vector<std::basic_string<char> > >}’ to ‘std::vector<std::vector<std::basic_string<char> > >::value_type&& {aka std::vector<std::basic_string<char> >&&}’
Makefile:28: recipe for target 'Structure.o' failed
make: *** [Structure.o] Error 1

How could I implement a vector of stack?

I am currently trying to implement a class with a vector of stacks. The class shall work as a stack to other objects but distribute the data to different stacks of a maximum size internally. If a stack is full a new one is created and pushed to the internal vector.
My current approach generates errors:
prog.cpp: In instantiation of ‘SetOfStack<T>::SetOfStack(int) [with T = int]’:
prog.cpp:54:32: required from here
prog.cpp:13:17: error: no matching function for call to ‘std::vector<std::stack<int, std::deque<int, std::allocator<int> > >, std::allocator<std::stack<int, std::deque<int, std::allocator<int> > > > >::push_back(std::stack<int, std::deque<int, std::allocator<int> > >*)’
stacks.push_back( new stack<T> );
^
/usr/include/c++/4.8/bits/stl_vector.h:901:7: note: no known conversion for argument 1 from ‘std::stack<int, std::deque<int, std::allocator<int> > >*’ to ‘const value_type& {aka const std::stack<int, std::deque<int, std::allocator<int> > >&}’
/usr/include/c++/4.8/bits/stl_vector.h:919:7: note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::stack<int, std::deque<int, std::allocator<int> > >; _Alloc = std::allocator<std::stack<int, std::deque<int, std::allocator<int> > > >; std::vector<_Tp, _Alloc>::value_type = std::stack<int, std::deque<int, std::allocator<int> > >]
push_back(value_type&& __x)
^
/usr/include/c++/4.8/bits/stl_vector.h:919:7: note: no known conversion for argument 1 from ‘std::stack<int, std::deque<int, std::allocator<int> > >*’ to ‘std::vector<std::stack<int, std::deque<int, std::allocator<int> > >, std::allocator<std::stack<int, std::deque<int, std::allocator<int> > > > >::value_type&& {aka std::stack<int, std::deque<int, std::allocator<int> > >&&}’
prog.cpp: In instantiation of ‘void SetOfStack<T>::push(T) [with T = int]’:
prog.cpp:55:21: required from here
prog.cpp:22:25: error: ‘__gnu_cxx::__alloc_traits<std::allocator<std::stack<int, std::deque<int, std::allocator<int> > > > >::value_type’ has no member named ‘push_back’
stacks[current_stack].push_back(new stack<T>);
^
prog.cpp: In instantiation of ‘T SetOfStack<T>::pop() [with T = int]’:
prog.cpp:56:27: required from here
prog.cpp:34:25: error: ‘__gnu_cxx::__alloc_traits<std::allocator<std::stack<int, std::deque<int, std::allocator<int> > > > >::value_type’ has no member named ‘pop_back’
stacks[current_stack].pop_back();
^
Sample Code:
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
template <class T>
class SetOfStack {
public:
SetOfStack( int max_size ): current_stack(0), max_stack_size(max_size) {
stacks.reserve(10);
stacks.push_back( new stack<T> );
}
~SetOfStack() {
stacks.clear();
}
void push( T value ) {
stacks[current_stack].push(value);
if(stacks[current_stack].size() > max_stack_size) {
stacks[current_stack].push_back(new stack<T>);
current_stack++;
if(current_stack % 10 == 0 && current_stack > stacks.size()) {
stacks.reserve(stacks.size() + 10);
}
}
}
T pop() {
T value = stacks[current_stack].top();
stacks[current_stack].pop();
if(stacks[current_stack].size() == 0 && current_stack != 0 ) {
stacks[current_stack].pop_back();
current_stack--;
}
}
T popAt( int index ) {
T value = stacks[index].top();
stacks[index].pop();
}
private:
int current_stack;
int max_stack_size;
vector< stack<T> > stacks;
};
int main() {
// Test code
SetOfStack<int> s_o_s(3);
s_o_s.push(1);
cout << s_o_s.pop() << endl;
return 0;
}
The error you're getting is this line:
stacks.push_back( new stack<T> );
As well as this line:
stacks[current_stack].push_back(new stack<T>);
Because you have declared stacks as a non-pointer:
vector< stack<T> > stacks;
So you want to use just stack<T>() instead of new stack<T>
Additionally, std::stack does not have a function push_back, you need to use push instead.
stacks.push_back(stack<T>());
stacks[current_stack].push(value);
As well as pop and not pop_back():
stacks[current_stack].pop();
At which point, you no longer need the deletes I mentioned in my original comment, since it looks like you were not intending to call new

No match found for operator= (find value in vector<string>)

I'm clearly missing something here, but what?
Definition (... denotes valid code, not actual three points):
class CrmxFile {
private:
const std::vector<std::string> validValues;
int value;
public:
void setValue(std::string _value);
...
}
std::vector<std::string> CrmxFile = {...};
In the code I have this:
void Crmx::SetValue(std::string _value) {
std::vector<std::string>::iterator idx;
if((idx = std::find(validValues.begin(), validValues.end(), _value)) == validValues.end()) {
value = 0;
}
else {
value = idx - validValues.begin();
}
}
I compile this with gcc -c -std=c++0x and I get this error:
CrmxFile.cpp: In member function ‘void CrmxFile::SetValue(std::string)’:
CrmxFile.cpp:24:64: error: no match for ‘operator=’ in ‘idx = std::find [with _IIter = __gnu_cxx::__normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >, _Tp = std::basic_string<char>](Id3V1::validValues.std::vector<_Tp, _Alloc>::begin [with _Tp = std::basic_string<char>, _Alloc = std::allocator<std::basic_string<char> >, std::vector<_Tp, _Alloc>::const_iterator = __gnu_cxx::__normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >, typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::const_pointer = const std::basic_string<char>*](), Id3V1::validValues.std::vector<_Tp, _Alloc>::end [with _Tp = std::basic_string<char>, _Alloc = std::allocator<std::basic_string<char> >, std::vector<_Tp, _Alloc>::const_iterator = __gnu_cxx::__normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >, typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::const_pointer = const std::basic_string<char>*](), (*(const std::basic_string<char>*)(& _value)))’
CrmxFile.cpp:24:64: note: candidates are:
/usr/include/c++/4.6/bits/stl_iterator.h:702:11: note: __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >& __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >::operator=(const __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >&)
/usr/include/c++/4.6/bits/stl_iterator.h:702:11: note: no known conversion for argument 1 from ‘__gnu_cxx::__normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >’ to ‘const __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >&’
/usr/include/c++/4.6/bits/stl_iterator.h:702:11: note: __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >& __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >::operator=(__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >&&)
/usr/include/c++/4.6/bits/stl_iterator.h:702:11: note: no known conversion for argument 1 from ‘__gnu_cxx::__normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >’ to ‘__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >&&’
What am I missing? Or, alternatively, is there a better way of finding the index of a given value in a vector?
idx has to be a const_iterator since validValues is a const vector<...>.
std::vector<std::string>::const_iterator idx;
Since validValues is const, begin(), end(), and therefore this instantiation of std::find, all return std::vector<std::string>::const_iterator, not std::vector<std::string>::iterator. For const-safety, a const_iterator cannot convert to an iterator.
validValues is defined as const std::vector<std::string>. Therefore begin() and end() will return const_iterator, but you are trying to assign the result to a iterator. Converting a const_iterator to an iterator would break const correctness (since you could then go on and change the underlying object) and is therefore not allowed.
Change the definition of idx to be std::vector<std::string>::const_iterator and it should work.
"What am I missing?"
Is yours first validValues invalid?
I suggest:
void Crmx::SetValue(std::string _value) {
value = std::find(validValues.begin(), validValues.end(), _value) - validValues.begin();
}
and use the validValues.size as invalid value, not 0