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 c 14, 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.