Consider the following reference wrapper:
template <class T>
struct wrapper
{
wrapper(T& x): reference{x} {}
void set(const T& x) {reference = x;}
T& get() const {return reference;}
T& reference;
};
I am wondering:
template <class T> using const_wrapper = /* const wrapper<T> or wrapper<const T>?*/
int i = 42; wrapper<const char> w(i);
will compile but not work (I would like to block the constructor)iterator
and const_iterator
general have two different implementations?How to declare a const reference wrapper through a template alias only template
<class T> using const_wrapper = /* const wrapper<T> or wrapper<const T>?*/
Obviously that would be:
template <class T> using const_wrapper = wrapper<const T>;
The contained type is const
, not the wrapper.
Be advised however that your set
function cannot be called if T
is const
. This is for obvious reasons; you can't change a const
value.
How to solve the following problem:
int i = 42; wrapper<const char> w(i);
will compile but not work (I would like to block the constructor)
This is actually a bit complicated. What you have to do is cause compilation to fail if the user tries to use a type that does not exactly match T
. To do that, you need to use the =delete
feature of C++11:
template <class T>
struct wrapper
{
wrapper(T& x): reference{x} {}
template<typename U>
wrapper(const U &) = delete;
//...
};
That second constructor will be used when anyone passes a type that is not an exact match for T
. And since it is delete
d, you get a compiler error when people attempt to use it.
For what exact problem, iterator and const_iterator general have two different implementations?
Who says that they do? They are not even required to be different types (consider the iterators for set
for example), let alone required to have different implementations. They are simply distinct type aliases.