Below is a condensed version of my code that gives me a compiler error. The compiler tells me to put typename in front of 'std::deque::reverse_iterator', which makes sense. But if I do I receive the error at the bottom. What does it mean? How can it be resolved?
#include <iostream>
#include <deque>
template<class T>
class Stack{
public:
Stack(){}
~Stack(){}
void push(T c) { s.push_back(c); }
void inspect() const{
for(typename std::deque<T>::reverse_iterator i=s.rbegin(); i!=s.rend(); i++)
std::cout << *i << std::endl;
}
private:
typename std::deque<T> s;
};
int main(){
Stack<int> s;
s.push(1);
s.inspect();
return 0;
}
Error:
error: no matching function for call to 'std::_Deque_iterator<int, int&, int*>::_Deque_iterator(std::reverse_iterator<std::_Deque_iterator<int, const int&, const int*> >::iterator_type)'|
note: candidates are:|
note: std::_Deque_iterator<_Tp, _Ref, _Ptr>::_Deque_iterator(const iterator&) [with _Tp = int; _Ref = int&; _Ptr = int*; std::_Deque_iterator<_Tp, _Ref, _Ptr>::iterator = std::_Deque_iterator<int, int&, int*>]|
note: no known conversion for argument 1 from 'std::reverse_iterator<std::_Deque_iterator<int, const int&, const int*> >::iterator_type {aka std::_Deque_iterator<int, const int&, const int*>}' to 'const iterator& {aka const std::_Deque_iterator<int, int&, int*>&}'|
note: std::_Deque_iterator<_Tp, _Ref, _Ptr>::_Deque_iterator() [with _Tp = int; _Ref = int&; _Ptr = int*]|
note: candidate expects 0 arguments, 1 provided|
note: std::_Deque_iterator<_Tp, _Ref, _Ptr>::_Deque_iterator(_Tp*, std::_Deque_iterator<_Tp, _Ref, _Ptr>::_Map_pointer) [with _Tp = int; _Ref = int&; _Ptr = int*; std::_Deque_iterator<_Tp, _Ref, _Ptr>::_Map_pointer = int**]|
note: candidate expects 2 arguments, 1 provided|
There's nothing dependent about std::deque<T>, so there mustn't be a typename. Only things to the right of a :: where the left depends on a template parameter is dependent.
This is a good example of where using auto would help you more than just saving typing. You're in a const member function, but trying to use your data member's reverse_iterator, not const_reverse_iterator.
Change typename std::deque<T>::reverse_iterator to typename std::deque<T>::const_reverse_iterator, or, more simply, auto.
This is in addition to the extra typename on your data member.
Related
I would expect deduction guides to correctly deduce the type in below example, yet they don't:
#include <set>
struct Foo { };
bool cmp(const Foo&, const Foo& );
std::set my_set({Foo{}, Foo{}}, cmp);
The compiler error (both gcc/clang show similar diagnostic):
In file included from /opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/x86_64-linux-gnu/bits/c++allocator.h:33,
from /opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/bits/allocator.h:46,
from /opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/bits/stl_tree.h:64,
from /opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/set:60,
from <source>:1:
/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/ext/new_allocator.h: In instantiation of 'class __gnu_cxx::new_allocator<bool(const Foo&, const Foo&)>':
/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/bits/alloc_traits.h:634:11: recursively required by substitution of 'template<class _Alloc> struct std::__is_allocator<_Alloc, std::__void_t<typename _Alloc::value_type, decltype (declval<_Alloc&>().allocate(long unsigned int{}))> > [with _Alloc = std::allocator<bool(const Foo&, const Foo&)>]'
/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/bits/alloc_traits.h:634:11: required by substitution of 'template<class _Alloc> using _RequireAllocator = typename std::enable_if<std::__is_allocator<_Alloc>::value, _Alloc>::type [with _Alloc = std::allocator<bool(const Foo&, const Foo&)>]'
/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/bits/stl_set.h:938:5: required by substitution of 'template<class _InputIterator, class _Compare, class _Allocator, class, class, class> std::set(_InputIterator, _InputIterator, _Compare, _Allocator)-> std::set<typename std::iterator_traits<_Iter>::value_type, _Compare, _Allocator> [with _InputIterator = bool (*)(const Foo&, const Foo&); _Compare = std::less<bool(const Foo&, const Foo&)>; _Allocator = std::allocator<bool(const Foo&, const Foo&)>; <template-parameter-1-4> = void; <template-parameter-1-5> = std::less<bool(const Foo&, const Foo&)>; <template-parameter-1-6> = <missing>]'
<source>:7:36: required from here
/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/ext/new_allocator.h:96:7: error: 'const _Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::const_reference) const [with _Tp = bool(const Foo&, const Foo&); __gnu_cxx::new_allocator<_Tp>::const_pointer = bool (*)(const Foo&, const Foo&); __gnu_cxx::new_allocator<_Tp>::const_reference = bool (&)(const Foo&, const Foo&)]' cannot be overloaded with '_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = bool(const Foo&, const Foo&); __gnu_cxx::new_allocator<_Tp>::pointer = bool (*)(const Foo&, const Foo&); __gnu_cxx::new_allocator<_Tp>::reference = bool (&)(const Foo&, const Foo&)]'
96 | address(const_reference __x) const _GLIBCXX_NOEXCEPT
| ^~~~~~~
/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/ext/new_allocator.h:92:7: note: previous declaration '_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = bool(const Foo&, const Foo&); __gnu_cxx::new_allocator<_Tp>::pointer = bool (*)(const Foo&, const Foo&); __gnu_cxx::new_allocator<_Tp>::reference = bool (&)(const Foo&, const Foo&)]'
92 | address(reference __x) const _GLIBCXX_NOEXCEPT
| ^~~~~~~
Compiler returned: 1
Which to me seems to hint at compiler not using the constructor taking the initializer list, but instead attempting to treat it as 2-iterator version (perhaps I am not reading it correctly, of course).
What might be the cause of this? Am I misreading deduction guides or is it something else?
It is probably a compiler/library bug, as little variant works:
Being explicit about initializer_list (Demo):
std::set my_set(std::initializer_list<Foo>{Foo{}, Foo{}}, cmp);
adding allocator (Demo):
std::set my_set({Foo{}, Foo{}}, cmp, std::allocator<Foo>{});
using Functor (Demo):
struct MyComparer
{
bool operator()(const Foo&, const Foo&) const;
};
std::set my_set({Foo{}, Foo{}}, MyComparer{});
And changing library (libc++ versus libstdc++) gives different results Demo for additional allocator variant.
I'm learning some C++ features by implementing an octree class. I want the subscript operator on this class to return the octant corresponding to an index. How should I define the subscript operator on the class so that I can both (i) assign to the result and (ii) check if the result is empty or not?
Goal (i) is idiomatically achieved by making the subscript operator return a reference. But references can't refer to nothing, which is a legitimate return value if an octant is empty.
Goal (ii) can be achieved by making the subscript operator return an optional. But then it becomes non-trivial to modify the pointer to the octant – with std::optional<T>, T cannot be a reference.
Here is the broken example (except all instances of optional are prefixed by experimental in the real code because my GCC only has experimental support for C++17).
#include <optional>
#include <iostream>
using namespace std;
class Octree {
Octree* branch[8];
public:
Octree();
~Octree();
optional<Octree&> operator[](int index);
};
Octree::Octree() : branch{}
{
}
Octree::~Octree()
{
for (int i = 0; i < 8; i++) {
if (branch[i])
delete branch[i];
}
}
optional<Octree&> Octree::operator[](int index)
{
if (branch[index] == NULL)
return nullopt;
else
return &branch[index];
}
int main(int argc, char *argv[])
{
Octree o;
if (o[0])
cout << "Octant o[0] is not empty.\n";
else
cout << "Octant o[0] is empty.\n";
o[0] = new Octree(); // The intent is to modify o
return 0;
}
The compiler, as expected, colorfully rejects an optional reference.
In file included from parc.cpp:1:0:
/usr/include/c++/6/experimental/optional: In instantiation of ‘class std::experimental::fundamentals_v1::optional<Octree&>’:
parc.cpp:26:61: required from here
/usr/include/c++/6/experimental/optional:507:7: error: static assertion failed: Invalid instantiation of optional<T>
static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>,
^~~~~~~~~~~~~
/usr/include/c++/6/experimental/optional:713:7: error: forming pointer to reference type ‘Octree&’
operator->() const
^~~~~~~~
/usr/include/c++/6/experimental/optional:723:7: error: forming pointer to reference type ‘Octree&’
operator->()
^~~~~~~~
parc.cpp: In member function ‘std::experimental::fundamentals_v1::optional<Octree&> Octree::operator[](int)’:
parc.cpp:31:10: error: could not convert ‘&((Octree*)this)->Octree::branch[index]’ from ‘Octree**’ to ‘std::experimental::fundamentals_v1::optional<Octree&>’
return &branch[index];
^~~~~~~~~~~~~~
parc.cpp: In function ‘int main(int, char**)’:
parc.cpp:41:24: error: no match for ‘operator=’ (operand types are ‘std::experimental::fundamentals_v1::optional<Octree&>’ and ‘Octree*’)
o[0] = new Octree();
^
In file included from parc.cpp:1:0:
/usr/include/c++/6/experimental/optional:595:7: note: candidate: std::experimental::fundamentals_v1::optional<_Tp>& std::experimental::fundamentals_v1::optional<_Tp>::operator=(std::experimental::fundamentals_v1::nullopt_t) [with _Tp = Octree&]
operator=(nullopt_t) noexcept
^~~~~~~~
/usr/include/c++/6/experimental/optional:595:7: note: no known conversion for argument 1 from ‘Octree*’ to ‘std::experimental::fundamentals_v1::nullopt_t’
/usr/include/c++/6/experimental/optional:609:9: note: candidate: template<class _Up> std::enable_if_t<std::__and_<std::__not_<std::is_same<std::experimental::fundamentals_v1::optional<_Tp>, typename std::decay<_Up>::type> >, std::is_constructible<_Tp, _Up>, std::__not_<std::__and_<std::is_scalar<_Tp>, std::is_same<_Tp, typename std::decay<_Up>::type> > >, std::is_assignable<_Tp&, _Up> >::value, std::experimental::fundamentals_v1::optional<_Tp>&> std::experimental::fundamentals_v1::optional<_Tp>::operator=(_Up&&) [with _Up = _Up; _Tp = Octree&]
operator=(_Up&& __u)
^~~~~~~~
/usr/include/c++/6/experimental/optional:609:9: note: template argument deduction/substitution failed:
/usr/include/c++/6/experimental/optional:628:9: note: candidate: template<class _Up> std::enable_if_t<std::__and_<std::__not_<std::is_same<_T1, _U1> >, std::is_constructible<_Tp, const _Up&>, std::is_assignable<_Tp&, _Up>, std::__not_<std::__or_<std::is_constructible<_Tp, const std::experimental::fundamentals_v1::optional<_Up>&>, std::is_constructible<_Tp, std::experimental::fundamentals_v1::optional<_Up>&>, std::is_constructible<_Tp, const std::experimental::fundamentals_v1::optional<_Up>&&>, std::is_constructible<_Tp, std::experimental::fundamentals_v1::optional<_Up>&&>, std::is_convertible<const std::experimental::fundamentals_v1::optional<_Up>&, _Tp>, std::is_convertible<std::experimental::fundamentals_v1::optional<_Up>&, _Tp>, std::is_convertible<const std::experimental::fundamentals_v1::optional<_Up>&&, _Tp>, std::is_convertible<std::experimental::fundamentals_v1::optional<_Up>&&, _Tp> > >, std::__not_<std::__or_<std::is_assignable<_Tp&, const std::experimental::fundamentals_v1::optional<_Up>&>, std::is_assignable<_Tp&, std::experimental::fundamentals_v1::optional<_Up>&>, std::is_assignable<_Tp&, const std::experimental::fundamentals_v1::optional<_Up>&&>, std::is_assignable<_Tp&, std::experimental::fundamentals_v1::optional<_Up>&&> > > >::value, std::experimental::fundamentals_v1::optional<_Tp>&> std::experimental::fundamentals_v1::optional<_Tp>::operator=(const std::experimental::fundamentals_v1::optional<_Up>&) [with _Up = _Up; _Tp = Octree&]
operator=(const optional<_Up>& __u)
^~~~~~~~
/usr/include/c++/6/experimental/optional:628:9: note: template argument deduction/substitution failed:
parc.cpp:41:24: note: mismatched types ‘const std::experimental::fundamentals_v1::optional<_Tp>’ and ‘Octree*’
o[0] = new Octree();
^
In file included from parc.cpp:1:0:
/usr/include/c++/6/experimental/optional:653:9: note: candidate: template<class _Up> std::enable_if_t<std::__and_<std::__not_<std::is_same<_T1, _U1> >, std::is_constructible<_Tp, _Up>, std::is_assignable<_Tp&, _Up>, std::__not_<std::__or_<std::is_constructible<_Tp, const std::experimental::fundamentals_v1::optional<_Up>&>, std::is_constructible<_Tp, std::experimental::fundamentals_v1::optional<_Up>&>, std::is_constructible<_Tp, const std::experimental::fundamentals_v1::optional<_Up>&&>, std::is_constructible<_Tp, std::experimental::fundamentals_v1::optional<_Up>&&>, std::is_convertible<const std::experimental::fundamentals_v1::optional<_Up>&, _Tp>, std::is_convertible<std::experimental::fundamentals_v1::optional<_Up>&, _Tp>, std::is_convertible<const std::experimental::fundamentals_v1::optional<_Up>&&, _Tp>, std::is_convertible<std::experimental::fundamentals_v1::optional<_Up>&&, _Tp> > >, std::__not_<std::__or_<std::is_assignable<_Tp&, const std::experimental::fundamentals_v1::optional<_Up>&>, std::is_assignable<_Tp&, std::experimental::fundamentals_v1::optional<_Up>&>, std::is_assignable<_Tp&, const std::experimental::fundamentals_v1::optional<_Up>&&>, std::is_assignable<_Tp&, std::experimental::fundamentals_v1::optional<_Up>&&> > > >::value, std::experimental::fundamentals_v1::optional<_Tp>&> std::experimental::fundamentals_v1::optional<_Tp>::operator=(std::experimental::fundamentals_v1::optional<_Up>&&) [with _Up = _Up; _Tp = Octree&]
operator=(optional<_Up>&& __u)
^~~~~~~~
/usr/include/c++/6/experimental/optional:653:9: note: template argument deduction/substitution failed:
parc.cpp:41:24: note: mismatched types ‘std::experimental::fundamentals_v1::optional<_Tp>’ and ‘Octree*’
o[0] = new Octree();
^
In file included from parc.cpp:1:0:
/usr/include/c++/6/experimental/optional:493:11: note: candidate: std::experimental::fundamentals_v1::optional<Octree&>& std::experimental::fundamentals_v1::optional<Octree&>::operator=(const std::experimental::fundamentals_v1::optional<Octree&>&)
class optional
^~~~~~~~
/usr/include/c++/6/experimental/optional:493:11: note: no known conversion for argument 1 from ‘Octree*’ to ‘const std::experimental::fundamentals_v1::optional<Octree&>&’
/usr/include/c++/6/experimental/optional:493:11: note: candidate: std::experimental::fundamentals_v1::optional<Octree&>& std::experimental::fundamentals_v1::optional<Octree&>::operator=(std::experimental::fundamentals_v1::optional<Octree&>&&)
/usr/include/c++/6/experimental/optional:493:11: note: no known conversion for argument 1 from ‘Octree*’ to ‘std::experimental::fundamentals_v1::optional<Octree&>&&’
/usr/include/c++/6/experimental/optional: In instantiation of ‘void std::experimental::fundamentals_v1::_Optional_base<_Tp, false>::_M_construct(_Args&& ...) [with _Args = {Octree}; _Tp = Octree&]’:
/usr/include/c++/6/experimental/optional:384:11: required from ‘std::experimental::fundamentals_v1::_Optional_base<_Tp, false>::_Optional_base(std::experimental::fundamentals_v1::_Optional_base<_Tp, false>&&) [with _Tp = Octree&]’
/usr/include/c++/6/experimental/optional:493:11: required from here
/usr/include/c++/6/experimental/optional:439:11: error: new cannot be applied to a reference type
::new (std::__addressof(this->_M_payload))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_Stored_type(std::forward<_Args>(__args)...);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I'm sure there's a way of overloading assignment so that I can return an optional and then assign to it like I do in main above. Thanks for any pointers! ;-)
Goal(i) can be achieved by returning a helper class that overloads the = operator. Goal(ii) can be achieved by returning a helper class that overloads the bool operator.
Consider what happens when your operator[] returns a class that looks like this:
class Octree {
// Other declarations...
public:
// Other declarations...
struct value_at {
Octree *ptr;
operator bool() const { return ptr != nullptr; }
Octree &operator=(const Octree &v)
{
return *ptr=v;
}
};
value_at operator[](int index);
};
Constructing the value_at would be your homework assignment; but it's obvious that a returned object with a null ptr represents a nonexistent value, otherwise it points to the value being returned.
Now, your [] operator returns can be used in a boolean context, which evaluates to an indication of whether or not a value was returned, and assigning something to the returned value ends up assigning to the value that [] supposedly returned.
The = operator overload can also check if ptr is null, and throw an exception, as a debugging aid.
The helper class can also declare an operator Octree() const overload, so that the returned object appears to be even more transparent.
Having said all of the above: you could also return a std::optional<std::reference_wrapper<Octree>> which is actually closer aligned to the object described in your question. However using it, in practice, may prove to require some cumbersome syntax (assigning to such std::optional may not necessarily have the effect you're looking for). A simple helper class like this usually leads to a more natural, transparent usage.
I have a small working code for finding a range of items that uses a special compare method. But when I try to rewrite it with lower_bound() and upper_bound() function, I get a strange error. I have written a small code to show my problem. Here is the code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
int main() {
string str = "banana";
string keyword = "ana";
int sa_idx[] = {5, 3, 1, 0, 4, 2};
vector<int> sa(sa_idx, sa_idx + sizeof(sa_idx) / sizeof(int) );
auto cmp = [&str] (const int &a, const string &keyword) -> bool
{
return strncmp(str.c_str() + a, keyword.c_str(), keyword.length()) < 0;
};
cout << (upper_bound(sa.begin(), sa.end(), keyword, cmp) -
lower_bound(sa.begin(), sa.end(), keyword, cmp)) << endl;
return 0;
}
As you see, compare function uses keyword and value of sa array for compare decision. A standard says:
The type Type1 must be such that an object of type ForwardIt can be
dereferenced and then implicitly converted to Type1. The type Type2
must be such that an object of type T can be implicitly converted to
Type2.
My compare function has int type for first argument(because of vector<int> of array) and string for the second argument type(as type of keyword). But I don't know why I get following error:
In file included from /usr/include/c++/6/bits/stl_algobase.h:71:0,
from /usr/include/c++/6/bits/char_traits.h:39,
from /usr/include/c++/6/ios:40,
from /usr/include/c++/6/ostream:38,
from /usr/include/c++/6/iostream:39,
from prog.cpp:1:
/usr/include/c++/6/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Val_comp_iter<_Compare>::operator()(_Value&, _Iterator) [with _Value = const std::__cxx11::basic_string<char>; _Iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = main()::<lambda(const int&, const string&)>]’:
/usr/include/c++/6/bits/stl_algo.h:2049:14: required from ‘_ForwardIterator std::__upper_bound(_ForwardIterator, _ForwardIterator, const _Tp&, _Compare) [with _ForwardIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Tp = std::__cxx11::basic_string<char>; _Compare = __gnu_cxx::__ops::_Val_comp_iter<main()::<lambda(const int&, const string&)> >]’
/usr/include/c++/6/bits/stl_algo.h:2114:32: required from ‘_FIter std::upper_bound(_FIter, _FIter, const _Tp&, _Compare) [with _FIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Tp = std::__cxx11::basic_string<char>; _Compare = main()::<lambda(const int&, const string&)>]’
prog.cpp:19:57: required from here
/usr/include/c++/6/bits/predefined_ops.h:173:11: error: no match for call to ‘(main()::<lambda(const int&, const string&)>) (const std::__cxx11::basic_string<char>&, int&)’
{ return bool(_M_comp(__val, *__it)); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cpp:14:61: note: candidate: main()::<lambda(const int&, const string&)>
auto cmp = [&str] (const int &a, const string &keyword) -> bool
^~~~
prog.cpp:14:61: note: no known conversion for argument 1 from ‘const std::__cxx11::basic_string<char>’ to ‘const int&’
Have I missed something super obvious? Because it seems compiler looks for string as first argument of compare function.
Your problem here is that std::uppper_bound requires the cmp be of the signature
bool(T, decltype(*Iterator))
std::lower_bound has the opposite requirement though and wants
bool(decltype(*Iterator), T)
so you can't use the same comparator with both functions. There are other ways to modify the code but just adding a second comparator like
auto cmp1 = [&str](const string &keyword, const int &a) -> bool
{
return strncmp(keyword.c_str(), str.c_str() + a, keyword.length()) < 0;
};
auto cmp2 = [&str] (const int &a, const string &keyword) -> bool
{
return strncmp(str.c_str() + a, keyword.c_str(), keyword.length()) < 0;
};
cout << (upper_bound(sa.begin(), sa.end(), keyword, cmp1) -
lower_bound(sa.begin(), sa.end(), keyword, cmp2)) << endl;
allows the code to compile.
I have made a function that is supposed to output data types which include ints, chars, strings and a class called item. This is the function:
template < typename T >
void Output(const T* first, const T* last, char outforchar= '\0')
{
if (outforchar== '\0')
{
std::for_each(first, last, [](T i){std::cout << i;});
}
else
{
std::for_each(first, last, [outforchar](T i){std::cout << i << outforchar;});
}
}
While this function works for types like ints, chars, and strings. It doesn't work for the item class which has a >> operator which formats the input according to the specifications. The compiler throws this error:
./tempsorter.h:14:47: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
std::for_each(beg, end, [](T i){std::cout << i;});
^
In file included from /usr/include/c++/4.8.2/iostream:39:0,
from psort.cpp:16:
/usr/include/c++/4.8.2/ostream:602:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Product]’
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
In file included from /usr/include/c++/4.8.2/algorithm:62:0,
from ./tempsorter.h:2,
from psort.cpp:18:
/usr/include/c++/4.8.2/bits/stl_algo.h:4411:5: error: ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = const Item*; _Funct = Output(const T*, const T*, char) [with T = Item]::__lambda0]’, declared using local type ‘Output(const T*, const T*, char) [with T = Item]::__lambda0’, is used but never defined [-fpermissive]
for_each(_InputIterator __first, _InputIterator __last, _Function __f)
^
/usr/include/c++/4.8.2/bits/stl_algo.h:4411:5: error: ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = const Item*; _Funct = Output(const T*, const T*, char) [with T = Item]::__lambda1]’, declared using local type ‘Output(const T*, const T*, char) [with T = Item]::__lambda1’, is used but never defined [-fpermissive]
I understand this error and can get rid of it using something like:
for (auto i = first; i != last; ++i)
{
std::cout << i;
}
But then this gives me incorrect outputs so I can't use it at all.
I am expected to traverse through the various types with something like the following:
for (typename E::ConsItr i = e.Begin(); i != e.End(); ++i)
I can't seem to understand how to implement this into the function, what am I doing wrong?
First,
[](T const& i){std::cout << i;}
is probably better. In addition, you probably wrote your << operator wrong.
std::ostream& operator<<(std::ostream& os, const SomeType& x)
it should look like that, and possibly be a friend of your type. Ensure it is in the same namespace as your type. Or you overloades >> instead of <<
I've been trying to compile and have played around with the ampersands and still can't figure out what the error is. Any ideas?
qsort.cc:22:23: error: no matching function for call to ‘qsort<int>::quicksort(std::vector<int, std::allocator<int> >*)’
qsort.cc:22:23: note: candidate is:
qsort.h:16:6: note: void qsort<T>::quicksort(std::vector<T>&) [with T = int]
qsort.h:16:6: note: no known conversion for argument 1 from ‘std::vector<int, std::allocator<int> >*’ to ‘std::vector<int, std::allocator<int> >&’
Header:
template <class T>
class qsort
{
public:
void quicksort(vector<T> &v);
void qusort(vector<T> &v, int left, int right);
void print(vector<T> &v);
};
template <class T>
void qsort<T>::quicksort(vector<T> &v)
{
qusort(&v, 0, 0);
}
template <class T>
void qsort<T>::print(vector<T> &v)
{
for(int i = 0; i < v.size(); i++)
{
cout << v[i] << endl;
}
}
Main:
int main()
{
qsort<int> asort;
vector<int> v;
v.push_back(2);
v.push_back(1);
v.push_back(7);
v.push_back(3);
v.push_back(8);
v.push_back(4);
v.push_back(0);
v.push_back(9);
v.push_back(5);
v.push_back(6);
asort.quicksort(&v);
asort.print(&v);
return 0;
}
Updated errors after ampersand removed out of main function calls (the short version)
qsort.h: In member function ‘void quisort::qusort(std::vector&, int, int) [with T = int]’:
qsort.h:18:5: instantiated from ‘void quisort::quicksort(std::vector&) [with T = int]’
qsort.cc:22:22: instantiated from here
qsort.h:27:38: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
/usr/include/c++/4.6/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, _Alloc = std::allocator]’ [-fpermissive]
qsort.h:18:5: instantiated from ‘void quisort::quicksort(std::vector&) [with T = int]’
qsort.cc:22:22: instantiated from here
qsort.h:31:9: error: no match for ‘operator<’ in ‘(& v)->std::vector<_Tp, _Alloc>::operator[] [with _Tp = int, _Alloc = std::allocator, std::vector<_Tp, _Alloc>::reference = int&, std::vector<_Tp, _Alloc>::size_type = long unsigned int](((long unsigned int)i)) < pivot’
qsort.h:31:9: note: candidates are:
/usr/include/c++/4.6/bits/stl_pair.h:207:5: note: template bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&)
/usr/include/c++/4.6/bits/stl_iterator.h:291:5: note: template bool std::operator<(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&)
Your member function takes the arguments by reference. They don't take pointers (that which is returned by the address operator &). You simply need to pass the object and the reference will bind:
asort.quicksort(v);
asort.print(v);