Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Custom set comparison function in a template class

I was trying to figure out this exercise from a school exam.
They implemented an abstract template Book class, and the assignment is to implement a bookshelf class.
I tried to construct a set of book pointers with a custom comparator, but then I encounter a compilation error:

In template: reference to type 'const Book<std::basic_string<char>>' could not bind to an lvalue of type 'const std::_Rb_tree<...>

(I implemented a sub class BOOK2 just for debugging purposes)

This is the long given book abstract class

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#include <iostream>
#include <set>
#include <string>
#include <utility>

template <class T>
class Book
{
  // any member variables are inaccessible to descendants
 private:
  std::string _title; // do not call a copy-ctr
  T _author; // do not call a copy-ctr
  size_t _number_of_pages;
 public:
  Book(std::string title,
       T author,
       size_t number_of_pages)
      : _title(std::move(title)),
        _author(std::move(author)),
        _number_of_pages(number_of_pages)
  {}

  virtual ~Book() = default;

  const std::string& get_title() const
  { return _title; }

  const T& get_author()  const
  { return _author; }

  size_t get_number_of_pages() const
  { return _number_of_pages; }

 public:
  virtual Book<T>* clone() const = 0; // implemented *only* by descendent classes

  virtual bool is_available_on(const std::string& platform) const = 0; // implemented *only* by descendant classes

 protected:
  virtual void do_output(std::ostream& os) const // can be overridden; can be accessed *only* by descendants
  {
    os << _title << ", " << _author << ", " << _number_of_pages << " pages";
  }

  // output should depend on who book really is
  friend std::ostream& operator<<(std::ostream& os, const Book& book)
  {
    book.do_output(os);
    return os;
  }
};

This is what I implemented:

class Book2: public Book<std::string>{
 public:
  Book2(std::string &title,
        std::string &author,
        size_t number_of_pages)
      : Book<std::string>(title,author,number_of_pages){}

  bool is_available_on(const std::string &platform) const override{return
        true;}
  Book<std::basic_string<char>> * clone() const override{
    Book<std::basic_string<char>> * a{};
    return  a;
  }
};


template<class TP>
static bool book_comp(const Book<TP>& a,const Book<TP> & b){
  return a.get_title()<b.get_title();}

template<class TT>
class Bookshelf
{
 public:
  typedef bool(*book_comp_t)(const Book<TT>& a,const Book<TT> & b);
  // DO NOT CHANGE NEXT TWO LINES:
  auto& get_books() { return _books; } // DO NO CHANGE
  auto& get_books() const { return _books; } // DO NO CHANGE

  Bookshelf():_books(book_comp<TT>){}

  void add(Book<TT>& book)
  {
    size_t init_size=_books.size();
    _books.insert (&book);
    if(init_size==_books.size()){
      throw std::invalid_argument("book already in bookshlf");
    }
  }

  // sorted lexicographically by title
  friend std::ostream& operator<<(std::ostream& os, const Bookshelf<TT>&
      bookshelf)
  {
    for(const auto& book :bookshelf._books)
    {
      os << *book << std::endl;
    }
  }

 private:
  std::set<Book<TT>*,book_comp_t> _books;
};

int main ()
{
  std::string  a ="aba";
  std::string bb ="ima;";
  Book2 b = Book2(a, bb, 30);
  Bookshelf<std::string> shelf;
  std::cout<<b;
  shelf.add(b);
}

I tried changing the const qualifiers in some places, and it didn’t work.
I also tried without using the custom comparator function which worked ok.
I think this is probably some syntax error maybe?

>Solution :

std::set<Book<TT>*,book_comp_t> _books; is a set of Book<TT>*, and thus requires a comparator whose parameters are of type Book<TT>*, not const Book<TT>&

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading