Delete
Delete

Reputation: 299

Templating a Custom Container with a Custom Comparator

I have a custom container whose underlying data structure is an std::list. Currently the container is templated to accept any data type (here's the header of the class): template <typename T> class square_list.

Here is an example of the unit tests I am trying to pass:

template <class T> class RuntimeCmp
{
    public:
       enum cmp_mode { normal, reverse };
    private:
       cmp_mode mode;
    public:
       RuntimeCmp( cmp_mode m = normal ) : mode(m) { }
       bool operator()(T const& t1, T const& t2) const { return mode == normal ? t1 < t2 : t2 < t1; }
       bool operator==( RuntimeCmp const& rc ) { return mode == rc.mode; }
};

BOOST_AUTO_TEST_CASE( ut_ctor_compare_passed ) {
     RuntimeCmp<double> rc(RuntimeCmp<double>::reverse);
     square_list<double,RuntimeCmp<double>> s(rc);
     vector<double> data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    for (auto x : data)
        s.insert(x);

    BOOST_CHECK( std::equal( s.begin(), s.end(), data.rbegin() ) );
}

So my question is, do I need to create a new struct/class inside of my existing container in order to add a new template parameter to my container for this custom comparator AND do I need to add a constructor so that I can pass the parameters of this comparator to my container like in the unit test? Any examples of how do something similar to this? Or at least just get the templating working?

Upvotes: 0

Views: 314

Answers (2)

Jonathan Wakely
Jonathan Wakely

Reputation: 171461

do I need to create a new struct/class inside of my existing container in order to add a new template parameter to my container for this custom comparator

I'm not sure what you mean by "create a new struct/class". To add a new template parameter you just ... add a new template parameter:

template<typename T, typename Cmp> class square_list;

AND do I need to add a constructor so that I can pass the parameters of this comparator to my container like in the unit test?

Yes, of course. If you want to construct it with an argument of the comparator type then you need a suitable constructor.

template<typename T, typename Cmp>
  class square_list
  {
  public:
    square_list(const Cmp&);
    // ...
  };

You will need a member variable to store the comparator:

template<typename T, typename Cmp>
  class square_list
  {
  public:
    square_list(const Cmp& cmp) : m_cmp(cmp)
    { }

  private:
    Cmp m_cmp;
  };

Upvotes: 3

Mooing Duck
Mooing Duck

Reputation: 66981

I'm having trouble understanding your question, but maybe a review of the declaration and constructors of std::set will clarify your confusion. This is a container that sounds vaguely like yours, it contains a type of data, and sorts them using a comparitor object.

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class set;

set();

explicit set( const Compare& comp, const Allocator& alloc = Allocator() );

template< class InputIt >
set( InputIt first, InputIt last, 
    const Compare& comp = Compare(), 
    const Allocator& alloc = Allocator() );

template< class InputIt >
set( InputIt first, InputIt last, const Allocator& alloc = Allocator() );

set( const set& other );

set( const set& other, const Allocator& alloc );

set( set&& other );

set( set&& other, const Allocator& alloc );

set( std::initializer_list<value_type> init, 
    const Compare& comp = Compare(), 
    const Allocator& alloc = Allocator() );

set( std::initializer_list<value_type> init, const Allocator& alloc = Allocator() );

And you have to make sure to store the Compare comp; as a member inside your class. (There's actually a "better" way, but it's tricky, so start with having it as a normal member.)

Source: http://en.cppreference.com/w/cpp/container/set/set

Upvotes: 2

Related Questions