Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template constructor for iterators

Tags:

c++

stl

I want to create different types of containers, and I want to sort them with my SortedContainer class. (I don't want to use functions like std::sort() now).

std::deque<int> d; d.push_back(2); d.push_back(1);
SortedContainer<int> sc1(d.begin(), d.end());

In the SortedContainer class, I want to create a copy constructor, that handles the iterators of the containers (d.begin() and d.end()).

But if I create another type of container of STL, I want to do the same.

std::vector<int> v; v.push_back(2); d.push_back(1);
SortedContainer<int> sc2(v.begin(), v.end());

In this case, I'm using std::vector instead of std::deque. So basically, it would be a template constructor.

template <class T>
class SortedContainer
{
   //...
public:
 SortedContainer(template_iterator begin, template_iterator end)
 {
   //...
 }
};

I know if I added class template_iterator as a template parameter, it would work well.

SortedContainer<int, std::deque::const_iterator> sc1(d.begin(), d.end());

But I don't want to tell the containers' type when instantiating the SortedContainer class. I want to find it out when passing container.begin() and container.end() to its constructor.

I have already tried using std::function and some other kind of methods, but none of them worked.

like image 964
dudefromouterspace Avatar asked Mar 23 '26 15:03

dudefromouterspace


1 Answers

You can create a make_sorted_container function that does the deduction for you:

template <typename TContainer>
auto make_sorted_container(TContainer&& c)
{
    using element_type = std::decay_t<decltype(*std::begin(c))>;
    using iterator_type = decltype(std::begin(c));

    return SortedContainer<element_type, iterator_type>(std::begin(c), std::end(c));
}

It can be used as follows:

std::vector<int> v;
auto sv = make_sorted_container(v);

static_assert(std::is_same<
    decltype(sv), 
    SortedContainer<int, typename std::vector<int>::iterator>
>{});

wandbox example


In C++17, class template deduction will allow template arguments to be deduced by constructors. In this case you need a deduction guide:

template <class T, class TItr>
class SortedContainer
{
   //...
public:
    SortedContainer(TItr b, TItr e)            
    {
        //...
    }
};

// Deduction guide:
template <class TItr>
SortedContainer(TItr b, TItr e)
    -> SortedContainer<std::decay_t<decltype(*b)>, TItr>;

Can be used like this:

std::vector<int> v;
SortedContainer sv(v.begin(), v.end());

wandbox example

like image 186
Vittorio Romeo Avatar answered Mar 25 '26 03:03

Vittorio Romeo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!