Home > Software design >  How to obtain iterator type from template parameter, if template parameter is a reference type
How to obtain iterator type from template parameter, if template parameter is a reference type

Time:07-02

The question title may not be super clear, but hopefully the below explains what is my problem.

Let's say I have the following (simplified) class template:

template <typename T, typename Container = std::vector<T>>
class MyVector {
  using iterator = typename Container::iterator;
    
  Container data{};

public:
  MyVector(initializer_list<T> l) : data(l) {}
  iterator begin() { return data.begin(); }
};

If I create an object like MyVector<int> vec {1, 2, 3}; it works fine.

However, if I try to create an object like MyVector<int, std::vector<int>&> vec; (note the &), then in the iterator type definition I get the error:

Type 'std::vector<int> &' cannot be used prior to '::' because it has no members

I tried exploring std::remove_reference and changed the line to:

using iterator = typename std::remove_reference<Container>::type::iterator;

but this also doesn't work - the error I get in this case is:

No type named 'iterator' in 'std::remove_reference<std::vector<int>>'

What I would like to achieve is to have a type definition (for iterator) that works if Container is a std::vector<T> as well as a reference to std::vector<T> (or whatever Container type is used, e.g. std::array - which means I cannot simply use std::vector<T>::iterator in the typedef).

Is there any way to achieve this?

CodePudding user response:

The std::remove_reference will work here. Or you need std::remove_reference_t version of it

using iterator = std::remove_reference_t<Container>::iterator;
//                             ^^^^^^^^^^^^

That is mean, if you do not have access to the , provide a type alias for this

template< class T >
using remove_reference_t = typename remove_reference<T>::type;

Also note that, in order to work with

MyVector<int, std::vector<int>&> vec(v);
//                              ^^^^^^^^ --> not an ini-list

class MyVector must have a constructor

MyVector(Container c) : data(c) {} 

The std::initializer_list will not work with reference qualified container type.

Here is the demo

  • Related