-1

The intentions is to store some pointers in a std::set, but order them by their corresponding value, not the value of pointer itself. and here is the code:

#include <bits/stdc++.h>

using namespace std;

template<class T>
class Pointer_comp {
public:
  bool operator()(const T* p1, const T* p2)
  {
    return std::less<T>()(*p1, *p2);
  }
};

int main()
{
  string *str1 = new string("fbvf"), *str2 = new string("adkva"), *str3 = new string("nljkm");
  set<string*, Pointer_comp<string>> strs({str1, str2, str3});   


  return 0;
}

and here is the error i get:

In file included from /usr/include/c++/10/map:60,
                 from /usr/include/c++/10/x86_64-redhat-linux/bits/stdc++.h:81,
                 from /home/farzankhalili/CLionProjects/codeForces/main.cpp:1:
/usr/include/c++/10/bits/stl_tree.h: In instantiation of ‘static const _Key& std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_S_key(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type) [with _Key = std::__cxx11::basic_string<char>*; _Val = std::__cxx11::basic_string<char>*; _KeyOfValue = std::_Identity<std::__cxx11::basic_string<char>*>; _Compare = Pointer_comp<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::__cxx11::basic_string<char>*>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type = const std::_Rb_tree_node<std::__cxx11::basic_string<char>*>*]’:
/usr/include/c++/10/bits/stl_tree.h:808:22:   required from ‘static const _Key& std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_S_key(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Base_ptr) [with _Key = std::__cxx11::basic_string<char>*; _Val = std::__cxx11::basic_string<char>*; _KeyOfValue = std::_Identity<std::__cxx11::basic_string<char>*>; _Compare = Pointer_comp<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::__cxx11::basic_string<char>*>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Base_ptr = const std::_Rb_tree_node_base*]’
/usr/include/c++/10/bits/stl_tree.h:2206:40:   required from ‘std::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_hint_unique_pos(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, const key_type&) [with _Key = std::__cxx11::basic_string<char>*; _Val = std::__cxx11::basic_string<char>*; _KeyOfValue = std::_Identity<std::__cxx11::basic_string<char>*>; _Compare = Pointer_comp<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::__cxx11::basic_string<char>*>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree<std::__cxx11::basic_string<char>*, std::__cxx11::basic_string<char>*, std::_Identity<std::__cxx11::basic_string<char>*>, Pointer_comp<std::__cxx11::basic_string<char> >, std::allocator<std::__cxx11::basic_string<char>*> >::const_iterator; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char>*]’
/usr/include/c++/10/bits/stl_tree.h:2266:4:   required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique_(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Arg&&, _NodeGen&) [with _Arg = std::__cxx11::basic_string<char>* const&; _NodeGen = std::_Rb_tree<std::__cxx11::basic_string<char>*, std::__cxx11::basic_string<char>*, std::_Identity<std::__cxx11::basic_string<char>*>, Pointer_comp<std::__cxx11::basic_string<char> >, std::allocator<std::__cxx11::basic_string<char>*> >::_Alloc_node; _Key = std::__cxx11::basic_string<char>*; _Val = std::__cxx11::basic_string<char>*; _KeyOfValue = std::_Identity<std::__cxx11::basic_string<char>*>; _Compare = Pointer_comp<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::__cxx11::basic_string<char>*>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree<std::__cxx11::basic_string<char>*, std::__cxx11::basic_string<char>*, std::_Identity<std::__cxx11::basic_string<char>*>, Pointer_comp<std::__cxx11::basic_string<char> >, std::allocator<std::__cxx11::basic_string<char>*> >::iterator; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree<std::__cxx11::basic_string<char>*, std::__cxx11::basic_string<char>*, std::_Identity<std::__cxx11::basic_string<char>*>, Pointer_comp<std::__cxx11::basic_string<char> >, std::allocator<std::__cxx11::basic_string<char>*> >::const_iterator]’
/usr/include/c++/10/bits/stl_tree.h:1111:23:   required from ‘std::__enable_if_t<std::is_same<_Val, typename std::iterator_traits<_InputIterator>::value_type>::value> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_range_unique(_InputIterator, _InputIterator) [with _InputIterator = std::__cxx11::basic_string<char>* const*; _Key = std::__cxx11::basic_string<char>*; _Val = std::__cxx11::basic_string<char>*; _KeyOfValue = std::_Identity<std::__cxx11::basic_string<char>*>; _Compare = Pointer_comp<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::__cxx11::basic_string<char>*>; std::__enable_if_t<std::is_same<_Val, typename std::iterator_traits<_InputIterator>::value_type>::value> = void; typename std::iterator_traits<_InputIterator>::value_type = std::__cxx11::basic_string<char>*]’
/usr/include/c++/10/bits/stl_set.h:247:36:   required from ‘std::set<_Key, _Compare, _Alloc>::set(std::initializer_list<_Tp>, const _Compare&, const allocator_type&) [with _Key = std::__cxx11::basic_string<char>*; _Compare = Pointer_comp<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::__cxx11::basic_string<char>*>; std::set<_Key, _Compare, _Alloc>::allocator_type = std::allocator<std::__cxx11::basic_string<char>*>]’
/home/farzankhalili/CLionProjects/codeForces/main.cpp:64:61:   required from here
/usr/include/c++/10/bits/stl_tree.h:782:8: error: static assertion failed: comparison object must be invocable as const
  782 |        is_invocable_v<const _Compare&, const _Key&, const _Key&>,
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
273K
  • 29,503
  • 10
  • 41
  • 64
Farzan
  • 1
  • 2
  • Does it work if you try correct include statements? Prefer a lambda over a homespun functor. The set doesn't appear to be declared correctly, either, but I could be off on that. You provide the type of the comparator, but never provide the comparator itself. – sweenish Jun 02 '21 at 16:45
  • see [Why should I not #include ?](https://stackoverflow.com/q/31816095/2069064) – Barry Jun 02 '21 at 16:46
  • @sweenish nah, i tried that before asking, it wasn't that. Barry's answer was the solution. – Farzan Jun 02 '21 at 16:52
  • That's good. I'd still recommend lambdas over DIY functors and using proper headers, though. – sweenish Jun 02 '21 at 18:53

1 Answers1

4

As the error says:

/usr/include/c++/10/bits/stl_tree.h:782:8: error: static assertion failed: comparison object must be invocable as const

The comparison object must be invocable as const, but it is not. So you have to mark it const:

template<class T>
class Pointer_comp {
public:
  bool operator()(const T* p1, const T* p2) const
  //                                        ^~~~~
  {
    return std::less<T>()(*p1, *p2);
  }
};

Which can be reduced to:

struct Pointer_cmp {
    template <typename T>
    constexpr bool operator()(T const* p1, T const* p2) const {
        return *p1 < *p2;
    }
};
Barry
  • 286,269
  • 29
  • 621
  • 977