Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement remove_reference

I'm learning type traits and type transformation (modification?), so I came across std::remove_reference. I tried to implement it like this:

template <class T>
struct remove_reference { typedef T type; };

template <class T>
struct remove_reference<const T> { typedef const T type; };

template <class T>
struct remove_reference<T&> { typedef T type; };

template <class T>
struct remove_reference<const T&> { typedef const T type; };

Now when I use it:

remove_reference<int>::type x1;        // x1 is int : Ok
remove_reference<const int>::type x2;  // x2 is <type> : ???
remove_reference<int&>::type x3;       // x3 is int : Ok
remove_reference<const int&>::type x4; // x4 is <type> : ???

I'm using Visual Studio 2015 and it tells me the type of x2 and x4 is <type> so what am I missing here ?

Note:

  1. I'm doing { typedef const T type } to remove reference and keep constness...
  2. I don't know C++ standard implementation of std::remove_reference

Edit: There is nothing wrong with std::remove_reference, I'm just doing this for sake of learning ...

like image 431
Laith Avatar asked May 28 '16 19:05

Laith


1 Answers

I'm doing { typedef const T type } to remove reference and keep constness...

You don't need to do that. If you remove the reference from T& where T is const X then you get const X. There's no need to specialize for that.

You do need to deal with rvalue references though.

So your implementation should be:

template <class T>
struct remove_reference { typedef T type; };

template <class T>
struct remove_reference<T&> { typedef T type; };

template <class T>
struct remove_reference<T&&> { typedef T type; };

That doesn't change the fact your tests are not valid though. Using a recent build of VC++ I get more useful errors:

main.cpp(16): error C2734: 'x2': 'const' object must be initialized if not 'extern'
main.cpp(18): error C2734: 'x4': 'const' object must be initialized if not 'extern'

This correctly tells you that you are trying to define a const without giving it a value. That's not allowed, because it would have an indeterminate (i.e. garbage) value, and you couldn't set it!

That has nothing to do with your remove_reference, you'd get the same errors if you wrote this:

int x1;
const int x2;   // error!
int x3;
const int x4;   // error!

Your tests will work fine if you initialize the const variables:

remove_reference<int>::type x1;        // x1 is uninitialized
remove_reference<const int>::type x2 = 0;
remove_reference<int&>::type x3;       // x3 is uninitialized
remove_reference<const int&>::type x4 = 0;
like image 154
Jonathan Wakely Avatar answered Nov 01 '22 10:11

Jonathan Wakely