The following piece of code works as expected but gives an odd looking message during compilation. Not sure what to make of it, but just trying to understand what GCC is trying to convey. Is it an error or just a GCC oddity? This is not happening in gcc-10.2
#include <algorithm>
#include <array>
#include <stdexcept>
#include <optional>
template < typename T >
struct Optional : public std::optional < T >
{
using impl_t = std::optional < T >;
using impl_t::impl_t;
constexpr inline friend bool operator == (Optional const & lhs, Optional const & rhs)
{
return static_cast < impl_t const & >(lhs) == static_cast < impl_t const & >(rhs);
}
template < typename U, typename = std::enable_if_t < std::is_convertible_v < U, T > > >
constexpr inline friend bool operator == (const Optional& lhs, U const & rhs)
{
return lhs.has_value() && static_cast < impl_t const & >(lhs) == rhs;
}
};
[[maybe_unused]]
auto triggers_unusual_compile_warning()
{
constexpr std::array < Optional < int32_t >, 4 > c{{1, 2, 3, std::nullopt}};
if (std::count(c.begin(), c.end(), std::nullopt) != 1)
throw std::runtime_error("WTH!!!");
};
int main()
{
triggers_unusual_compile_warning();
}
That small program triggers the following message
/opt/compiler-explorer/gcc-8.2.0/include/c++/8.2.0/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Iter_equals_val<_Value>::operator()(_Iterator) [with _Iterator = const Optional<int>*; _Value = const std::nullopt_t]':
/opt/compiler-explorer/gcc-8.2.0/include/c++/8.2.0/bits/stl_algo.h:3194:12: required from 'typename std::iterator_traits<_Iterator>::difference_type std::__count_if(_InputIterator, _InputIterator, _Predicate) [with _InputIterator = const Optional<int>*; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<const std::nullopt_t>; typename std::iterator_traits<_Iterator>::difference_type = long int]'
/opt/compiler-explorer/gcc-8.2.0/include/c++/8.2.0/bits/stl_algo.h:4082:29: required from 'typename std::iterator_traits<_Iterator>::difference_type std::count(_IIter, _IIter, const _Tp&) [with _IIter = const Optional<int>*; _Tp = std::nullopt_t; typename std::iterator_traits<_Iterator>::difference_type = long int]'
<source>:29:52: required from here
/opt/compiler-explorer/gcc-8.2.0/include/c++/8.2.0/optional:1371:5: note: candidate 1: 'constexpr bool std::operator==(const std::optional<_Tp>&, std::nullopt_t) [with _Tp = int]'
operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
^~~~~~~~
<source>:12:34: note: candidate 2: 'constexpr bool operator==(const Optional<int>&, const Optional<int>&)'
constexpr inline friend bool operator == (Optional const & lhs, Optional const & rhs)
^~~~~~~~
ASM generation compiler returned: 0
In file included from <source>:4:
/opt/compiler-explorer/gcc-8.2.0/include/c++/8.2.0/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Iter_equals_val<_Value>::operator()(_Iterator) [with _Iterator = const Optional<int>*; _Value = const std::nullopt_t]':
/opt/compiler-explorer/gcc-8.2.0/include/c++/8.2.0/bits/stl_algo.h:3194:12: required from 'typename std::iterator_traits<_Iterator>::difference_type std::__count_if(_InputIterator, _InputIterator, _Predicate) [with _InputIterator = const Optional<int>*; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<const std::nullopt_t>; typename std::iterator_traits<_Iterator>::difference_type = long int]'
/opt/compiler-explorer/gcc-8.2.0/include/c++/8.2.0/bits/stl_algo.h:4082:29: required from 'typename std::iterator_traits<_Iterator>::difference_type std::count(_IIter, _IIter, const _Tp&) [with _IIter = const Optional<int>*; _Tp = std::nullopt_t; typename std::iterator_traits<_Iterator>::difference_type = long int]'
<source>:29:52: required from here
/opt/compiler-explorer/gcc-8.2.0/include/c++/8.2.0/optional:1371:5: note: candidate 1: 'constexpr bool std::operator==(const std::optional<_Tp>&, std::nullopt_t) [with _Tp = int]'
operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
^~~~~~~~
<source>:12:34: note: candidate 2: 'constexpr bool operator==(const Optional<int>&, const Optional<int>&)'
constexpr inline friend bool operator == (Optional const & lhs, Optional const & rhs)
^~~~~~~~
Execution build compiler returned: 0
The problem with the code is that the equality operator is ambiguous. A std::nullopt can be converted to a std::optional.
So, by instantiating a operator== when you call std::count, the compiler cannot choose between the operator== from the library and your operator== declared as
constexpr inline friend bool operator == (Optional const & lhs, Optional const & rhs)
How exactly to solve this problem depends on the details you have in mind. For example, if you add an explicit comparison with std::nullopt_t
constexpr inline friend bool operator == (Optional const & lhs, std::nullopt_t const & rhs)
{
return static_cast < impl_t const & >(lhs) == static_cast < impl_t const & >(rhs);
}
you force the compiler to choose your more-specific implementation, and the error disappears.
But of course, a good solution depends on what you have in mind.
Related
In MyRect.h:
struct MyRect
{
MyRect(std::initializer_list<int> i);
MyRect();
int16_t m_left=0, m_right=0, m_top=0, m_bottom=0 ;
int16_t no_sequence=0 ;
int16_t i=-1 ;
bool selected=false ;
} ;
bool operator==(const MyRect& r1, const MyRect& r2) ;
bool operator<(const MyRect& r1, const MyRect& r2);
In MyRect.cpp:
bool operator==(const MyRect& r1, const MyRect& r2)
{
return r1.m_left==r2.m_left &&
r1.m_right==r2.m_right &&
r1.m_top==r2.m_top &&
r1.m_bottom==r2.m_bottom ;
}
bool operator<(const MyRect& r1, const MyRect& r2)
{
if (r1.m_left != r2.m_left)
return r1.m_left < r2.m_left;
if (r1.m_right != r2.m_right)
return r1.m_right < r2.m_right;
if (r1.m_top != r2.m_top)
return r1.m_top < r2.m_top;
if (r1.m_bottom != r2.m_bottom)
return r1.m_bottom < r2.m_bottom;
//if we got here, r1==r2
return false;
}
In binpack.cpp:
#include "MyRect.h"
...
vector<MyRect> selected_neighboors ;
std::sort(selected_neighboors.begin(), selected_neighboors.end()) ;
Using g++10 (C++20) binpack.cpp compiles. No issues.
If I change to:
ranges::sort(selected_neighboors);
It does not compile any more.
/home/edouda/linkedboxdraw/binpack.cpp: In function ‘void collapse(std::vector<MyRect>&)’:
/home/edouda/linkedboxdraw/binpack.cpp:617:36: error: no match for call to ‘(const std::ranges::__sort_fn) (std::vector<MyRect>&)’
617 | ranges::sort(selected_neighboors) ;
| ^
In file included from /usr/include/c++/10/algorithm:64,
from /home/edouda/linkedboxdraw/MyRect.h:14,
from /home/edouda/linkedboxdraw/binpack.h:12,
from /home/edouda/linkedboxdraw/binpack.cpp:8:
/usr/include/c++/10/bits/ranges_algo.h:2019:7: note: candidate: ‘template<class _Iter, class _Sent, class _Comp, class _Proj> requires (random_access_iterator<_Iter>) && (sentinel_for<_Sent, _Iter>) && (sortable<_Iter, _Comp, _Proj>) constexpr _Iter std::ranges::__sort_fn::operator()(_Iter, _Sent, _Comp, _Proj) const’
2019 | operator()(_Iter __first, _Sent __last,
| ^~~~~~~~
/usr/include/c++/10/bits/ranges_algo.h:2019:7: note: template argument deduction/substitution failed:
/home/edouda/linkedboxdraw/binpack.cpp:617:36: note: candidate expects 4 arguments, 1 provided
617 | ranges::sort(selected_neighboors) ;
| ^
In file included from /usr/include/c++/10/algorithm:64,
from /home/edouda/linkedboxdraw/MyRect.h:14,
from /home/edouda/linkedboxdraw/binpack.h:12,
from /home/edouda/linkedboxdraw/binpack.cpp:8:
/usr/include/c++/10/bits/ranges_algo.h:2032:7: note: candidate: ‘constexpr std::ranges::borrowed_iterator_t<_Range> std::ranges::__sort_fn::operator()(_Range&&, _Comp, _Proj) const [with _Range = std::vector<MyRect>&; _Comp = std::ranges::less; _Proj = std::identity; std::ranges::borrowed_iterator_t<_Range> = std::conditional<true, __gnu_cxx::__normal_iterator<MyRect*, std::vector<MyRect> >, std::ranges::dangling>::type]’
2032 | operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
| ^~~~~~~~
/usr/include/c++/10/bits/ranges_algo.h:2032:7: note: constraints not satisfied
In file included from /usr/include/c++/10/compare:39,
from /usr/include/c++/10/bits/stl_pair.h:65,
from /usr/include/c++/10/bits/stl_algobase.h:64,
from /usr/include/c++/10/vector:60,
from /home/edouda/linkedboxdraw/MyRect.h:12,
from /home/edouda/linkedboxdraw/binpack.h:12,
from /home/edouda/linkedboxdraw/binpack.cpp:8:
/usr/include/c++/10/concepts: In instantiation of ‘constexpr std::ranges::borrowed_iterator_t<_Range> std::ranges::__sort_fn::operator()(_Range&&, _Comp, _Proj) const [with _Range = std::vector<MyRect>&; _Comp = std::ranges::less; _Proj = std::identity; std::ranges::borrowed_iterator_t<_Range> = std::conditional<true, __gnu_cxx::__normal_iterator<MyRect*, std::vector<MyRect> >, std::ranges::dangling>::type]’:
/home/edouda/linkedboxdraw/binpack.cpp:617:36: required from here
/usr/include/c++/10/concepts:338:13: required for the satisfaction of ‘invocable<_Fn, _Args ...>’ [with _Fn = std::ranges::less&; _Args = {value_type<MyRect>&, value_type<MyRect>&}]
/usr/include/c++/10/concepts:342:13: required for the satisfaction of ‘regular_invocable<_Fn, _Args ...>’ [with _Fn = std::ranges::less&; _Args = {value_type<MyRect>&, value_type<MyRect>&}]
/usr/include/c++/10/concepts:346:13: required for the satisfaction of ‘predicate<_Rel, _Tp, _Tp>’ [with _Rel = std::ranges::less&; _Tp = MyRect&]
/usr/include/c++/10/concepts:351:13: required for the satisfaction of ‘relation<_Rel, _Tp, _Up>’ [with _Rel = std::ranges::less&; _Tp = MyRect&; _Up = MyRect&]
/usr/include/c++/10/concepts:361:13: required for the satisfaction of ‘strict_weak_order<_Fn&, typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Arg>::type>::type, std::indirectly_readable_traits<typename std::remove_cv<typename std::remove_reference<_Arg>::type>::type> >::type::value_type&, typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Arg>::type>::type, std::indirectly_readable_traits<typename std::remove_cv<typename std::remove_reference<_Arg>::type>::type> >::type::value_type&>’ [with _Fn = std::ranges::less; _Arg = std::projected<__gnu_cxx::__normal_iterator<MyRect*, std::vector<MyRect, std::allocator<MyRect> > >, std::identity>; _Arg = std::projected<__gnu_cxx::__normal_iterator<MyRect*, std::vector<MyRect, std::allocator<MyRect> > >, std::identity>]
/usr/include/c++/10/bits/iterator_concepts.h:690:13: required for the satisfaction of ‘indirect_strict_weak_order<_Rel, std::projected<_Iter, _Proj>, std::projected<_Iter, _Proj> >’ [with _Rel = std::ranges::less; _Iter = __gnu_cxx::__normal_iterator<MyRect*, std::vector<MyRect, std::allocator<MyRect> > >; _Proj = std::identity]
/usr/include/c++/10/bits/iterator_concepts.h:865:13: required for the satisfaction of ‘sortable<decltype (std::__detail::__ranges_begin(declval<_Container&>())), _Comp, _Proj>’ [with _Container = std::vector<MyRect, std::allocator<MyRect> >&; _Comp = std::ranges::less; _Proj = std::identity]
/usr/include/c++/10/concepts:338:25: note: the expression ‘is_invocable_v<_Fn, _Args ...> [with _Fn = std::ranges::less&; _Args = {value_type<MyRect>&, value_type<MyRect>&}]’ evaluated to ‘false’
338 | concept invocable = is_invocable_v<_Fn, _Args...>;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make[2]: *** [CMakeFiles/latuile.dir/build.make:76: CMakeFiles/latuile.dir/binpack.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:78: CMakeFiles/latuile.dir/all] Error 2
make: *** [Makefile:95: all] Error 2
ranges::sort uses ranges::less to compare MyRect by default, which is defined in [range.cmp]:
struct ranges::less {
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
using is_transparent = unspecified;
};
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
Constraints: T and U satisfy totally_ordered_with.
Its operator() requires that T and U must satisfy total_ordered_with:
template<class T, class U>
concept totally_ordered_with =
totally_ordered<T> && totally_ordered<U> && ...
which requires that T must satisfy totally_ordered:
template<class T>
concept totally_ordered =
equality_comparable<T> && partially-ordered-with<T, T>;
which requires that T must satisfy partially-ordered-with:
template<class T, class U>
concept partially-ordered-with = // exposition only
requires(const remove_reference_t<T>& t, const remove_reference_t<U>& u) {
{ t < u } -> boolean-testable;
{ t > u } -> boolean-testable;
{ t <= u } -> boolean-testable;
{ t >= u } -> boolean-testable;
{ u < t } -> boolean-testable;
{ u > t } -> boolean-testable;
{ u <= t } -> boolean-testable;
{ u >= t } -> boolean-testable;
};
which requires that the full set of the relational operators must be well-formed.
Since you did not define a suitable operator>, operator<= and other relational operators for MyRect, the constraints are not satisfied.
You can add operator<=> to MyRect to make it totally_ordered, or use unconstrained std::less for comparison:
std::vector<MyRect> selected_neighboors;
ranges::sort(selected_neighboors, std::less{});
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 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'm beginer in templates and cann't resolve one compiler issue. The problem is in the following:
I have two classes.
class TMessage
{
public:
int Priority;
TMessageType Type;
bool operator> (const TMessage& m)
{
return m.Priority > Priority;
}
bool operator< (const TMessage& m)
{
return m.Priority < Priority;
}
};
template<typename T> class TMessageQueue
{
public:
T* Buffer;
int QueueStartOffset;
void SortMessages(int putPointer)
{
std::sort(Buffer+QueueStartOffset,Buffer+ putPointer);
}
};
In file included from /usr/include/c++/4.8/algorithm:62:0,
from TMessageQueue.h:2,
from TWriterThread.h:2,
from TWriterThread.cpp:1:
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘_RandomAccessIterator std::__unguarded_partition(_RandomAccessIterator, _RandomAccessIterator, const _Tp&) [with _RandomAccessIterator = TMessage*; _Tp = TMessage]’:
/usr/include/c++/4.8/bits/stl_algo.h:2283:70: required from ‘_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = TMessage*]’
/usr/include/c++/4.8/bits/stl_algo.h:2315:54: required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = TMessage*; _Size = long int]’
/usr/include/c++/4.8/bits/stl_algo.h:5461:36: required from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = TMessage*]’
TMessageQueue.h:158:60: required from ‘void TMessageQueue::SortMessages(int) [with T = TMessage]’
TMessageQueue.h:143:26: required from ‘TRetCode TMessageQueue::Put(T&) [with T = TMessage]’
TWriterThread.cpp:59:34: required from here
/usr/include/c++/4.8/bits/stl_algo.h:2245:19: error: passing ‘const TMessage’ as ‘this’ argument of ‘bool TMessage::operator<(const TMessage&)’ discards qualifiers [-fpermissive]
while (__pivot < *__last)
^
make: *** [all] Error 1
What is the problem? Used compiler g++.
The operator< and operator> methods need to be const
bool operator> (const TMessage& m) const { ... }
bool operator< (const TMessage& m) const { ... }
In addition the first answer by simpel01,
this bad code:
bool operator> (const TMessage& m)
{
return m.Priority > Priority;
}
bool operator< (const TMessage& m)
{
return m.Priority < Priority;
}
In operator > must return this->Priority > m.Priority not m.Priority > this->Priority because operator > activated by object this and actually you want to say if I'm (object this) big than from m.
what you do is reverse!
and fix operator < to this->Priority < m.Priority
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.