How could I implement a vector of stack? - c++

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

Related

ranges views size does not compile

#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.

Getting error when using comparator with upper_bound?

When I run "upper_bound" with a comparator it gives me this error: error: reference to type 'const std::vector<int, std::allocator>' could not bind to an lvalue of type 'const int. Anyone know the issue?
static bool compareInterval(const vector<int>& a, const vector<int>& b) {
return (a[0] < b[0]);
}
vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {
vector<int> ret(n, 0);
sort(bookings.begin(), bookings.end(), compareInterval);
for (int i = 0; i < n; ++i) {
auto low=upper_bound(bookings.begin(), bookings.end(), i, compareInterval);
}
return ret;
}
In file included from prog_joined.cpp:1: In file included from
./precompiled/headers.h:13: In file included from
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/cmath:1927:
In file included from
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/specfun.h:45:
In file included from
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_algobase.h:71:
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/predefined_ops.h:215:24:
error: reference to type 'const std::vector<int, std::allocator>'
could not bind to an lvalue of type 'const int'
{ return bool(_M_comp(__val, __it)); }
^~~~~ /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_algo.h:2051:8:
note: in instantiation of function template specialization
'__gnu_cxx::__ops::_Val_comp_iter<bool ()(const std::vector<int,
std::allocator> &, const std::vector<int, std::allocator>
&)>::operator()<const int,
__gnu_cxx::__normal_iterator<std::vector<int, std::allocator> *, std::vector<std::vector<int, std::allocator>,
std::allocator<std::vector<int, std::allocator>>>>>' requested
here
if (__comp(__val, __middle))
^ /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_algo.h:2116:19:
note: in instantiation of function template specialization
'std::__upper_bound<__gnu_cxx::__normal_iterator<std::vector<int,
std::allocator> , std::vector<std::vector<int,
std::allocator>, std::allocator<std::vector<int,
std::allocator>>>>, int, __gnu_cxx::__ops::_Val_comp_iter<bool
()(const std::vector<int, std::allocator> &, const
std::vector<int, std::allocator> &)>>' requested here
return std::__upper_bound(__first, __last, __val,
^ Line 12: Char 22: note: in instantiation of function template specialization
'std::upper_bound<__gnu_cxx::__normal_iterator<std::vector<int,
std::allocator> , std::vector<std::vector<int,
std::allocator>, std::allocator<std::vector<int,
std::allocator>>>>, int, bool ()(const std::vector<int,
std::allocator> &, const std::vector<int, std::allocator>
&)>' requested here
auto low=upper_bound(bookings.begin(), bookings.end(), i, compareInterval);
^ 1 error generated.
It turns out "i" needs to be wrapped up to become the same type as an element of bookings

c++ - copy constructor for template class

My class is a matrix composed out of vectors of vectors, and I seem to have problems in my constructor:
#include <vector>
#include <exception>
#include <iostream>
using namespace std;
template<class T>
class Matrix
{
private:
unsigned int _rows;
unsigned int _cols;
vector <vector<T>> _matrix;
public:
const unsigned int INITIAL_ROW_SIZE = 1;
const unsigned int INITIAL_COL_SIZE = 1;
Matrix () : _rows(INITIAL_COL_SIZE), _cols(INITIAL_COL_SIZE),
_matrix(1,vector<T>(1)) {
cout << "ctor" << endl;
}
Matrix (unsigned int rows, unsigned int cols) : _rows(rows), _cols(cols),_matrix(_rows,vector<T>(_cols) {
}
Matrix (const Matrix<T> &other) :Matrix(other._rows, other._cols)
{
for(int i = 0; i < _rows; i++)
{
copy(other._matrix[i].begin(), other._matrix[i].end(), _matrix[i]);
}
};
}
the code will not compile when i try to use the copy constructor,
as in Matric<int> m(5,5); Matrix<int> n=(m); because:
In file included from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/vector:60:0,
from /cppex3/ex3/Matrix.hpp:8,
from /cppex3/ex3/Tester.cpp:6:
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_algobase.h: In instantiation of '_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = const std::vector<int, std::allocator<int> >*; _OI = std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >]':
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_algobase.h:438:45: required from '_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = __gnu_cxx::__normal_iterator<const std::vector<int, std::allocator<int> >*, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >; _OI = std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >]'
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_algobase.h:471:8: required from '_OI std::copy(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<const std::vector<int, std::allocator<int> >*, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >; _OI = std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >]'
/ex3/Matrix.hpp:42:13: required from 'Matrix<T>::Matrix(const Matrix<T>&) [with T = int]'
/ex3/Tester.cpp:25:20: required from here
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_algobase.h:394:57: error: no type named 'value_type' in '[01mstruct std::iterator_traits<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >'
typedef typename iterator_traits<_OI>::value_type _ValueTypeO;
^
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_algobase.h:399:9: error: no type named 'value_type' in 'struct std::iterator_traits<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >'
&& __are_same<_ValueTypeI, _ValueTypeO>::__value);
^
I suspect my initalization of the _matrix member is not correct, but I'm not sure. it could also by std::copy but the syntax seems correct.
Try with
copy(other._matrix[i].begin(), other._matrix[i].end(),
std::back_inserter(_matrix[i]));
or with
Matrix (const Matrix<T> &other)
: _rows{other._rows}, _cols{other._cols}, _matrix{other._matrix}
{
}
Try this code, it works
Replace your
copy(other._matrix[i].begin(), other._matrix[i].end(), _matrix[i]);
with
copy(other._matrix[i].begin(), other._matrix[i].end(), _matrix[i].begin());
Below is the complete code.
#include <vector>
#include <exception>
#include <iostream>
using namespace std;
template<class T>
class Matrix
{
private:
unsigned int _rows;
unsigned int _cols;
vector <vector<T> > _matrix;
public:
Matrix () : _rows(1), _cols(1),
_matrix(1,vector<T>(1))
{
cout << "ctor" << endl;
}
Matrix (unsigned int rows, unsigned int cols) : _rows(rows), _cols(cols)
{
_matrix=vector< vector<T> >(rows,vector<T>(cols));
}
Matrix (const Matrix<T> &other)
: _rows{other._rows}, _cols{other._cols}, _matrix{other._matrix}
{
for(int i = 0; i < _rows; i++)
{
std::copy(other._matrix[i].begin(), other._matrix[i].end(), _matrix[i].begin());
}
}
};
int main(int argc, char const *argv[])
{
Matrix<int> m(5,5);
Matrix<int> n1(m);
Matrix<int> n2(m);
return 0;
}
Also
Matrix (const Matrix<T> &other) :Matrix(other._rows, other._cols);
replaced it with
Matrix (const Matrix<T> &other) {
Matrix(other._rows, other._cols);
...

Template function with std::async in clang

I was looking at the example for std::async here, as follows:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>
template <typename RAIter>
int parallel_sum(RAIter beg, RAIter end)
{
auto len = std::distance(beg, end);
if(len < 1000)
return std::accumulate(beg, end, 0);
RAIter mid = beg + len/2;
auto handle = std::async(std::launch::async,
parallel_sum<RAIter>, mid, end);
int sum = parallel_sum(beg, mid);
return sum + handle.get();
}
int main()
{
std::vector<int> v(10000, 1);
std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
}
I tried compiling it with the web compiler for Clang 3.4 and it resulted in the output The sum is instead of the expected The sum is 1000.
I copied the example and compiled with clang 3.5-1ubuntu1 / gcc 4.8 on Ubuntu 14.04.1 64-bit using the following command:
clang++ -g main.cpp -std=c++1y -o out -pthread;
I get the following error:
main.cpp:15:19: error: no matching function for call to 'async'
auto handle = std::async(std::launch::async,
^~~~~~~~~~
main.cpp:24:35: note: in instantiation of function template specialization
'parallel_sum<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> >
> >' requested here
std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/future:1523:5: note:
candidate template ignored: substitution failure [with _Fn = int
(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >), _Args =
<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &>]:
function cannot return function type 'int (__gnu_cxx::__normal_iterator<int *,
std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int *,
std::vector<int, std::allocator<int> > >)'
async(launch __policy, _Fn&& __fn, _Args&&... __args)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/future:1543:5: note:
candidate template ignored: substitution failure [with _Fn = std::launch, _Args = <int
(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >),
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &>]: no
type named 'type' in 'std::result_of<std::launch (int
(*)(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >),
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &)>'
async(_Fn&& __fn, _Args&&... __args)
^
1 error generated.
make: *** [all] Error 1
Is this a bug in clang, gcc, libstdc++, or am I missing something?
I think this is a bug in clang++. Unless there's a strange restricted rule that I'm not aware of, an id-expression referring to a function is an lvalue. However, clang++ makes a distinction between function template specializations and ordinary functions in the deduction for a universal reference:
#include <iostream>
template<class T>
void print_type()
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
template <class T>
int foo(bool) { return 42; }
int bar(bool) { return 42; }
template<class T>
void deduce(T&&)
{
print_type<T>();
}
int main()
{
deduce(foo<bool>);
deduce(bar);
}
Output, clang++ up to and including an early 3.5:
void print_type() [T = int (bool)]
void print_type() [T = int (&)(bool)]
Live example
std::result_of is used in libstdc++'s implementation of std::async to get the return type of the function (snippet from here):
template<typename _Fn, typename... _Args>
future<typename result_of<_Fn(_Args...)>::type>
async(launch __policy, _Fn&& __fn, _Args&&... __args)
If we pass foo<bool> as the second argument, clang++ deduces _Fn == int (bool).
The type of the function (object) is combined with the argument types for result_of. This is probably a relict of C++03, where we didn't have variadic templates yet. The argument types are passed to allow result_of to resolve overloaded functions like an overloaded operator() in case _Fn is a class type.
However, if _Fn is deduced not to a function reference, but to a function type, the combination _Fn(_Args...) forms an illegal type: a function returning a function:
_Fn == int(bool)
_Args... == bool
==> _Fn(_Args...) == int(bool)(bool)
But there's more to it: The above declaration of async is defective, see LWG 2021. Howard Hinnant changed the declaration in libc++ to:
template <class F, class... Args>
future < typename result_of<
typename decay<F>::type(typename decay<Args>::type...)
>::type
>
async(launch policy, F&& f, Args&&... args);
so libc++ decays the function to a function pointer. The problem caused by the missing lvalue reference disappears.

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