Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does using std::remove_reference and std::remove_const in different order produce different results?

In the following code I have used std::remove_const and std::remove_reference but in different order in two cases which are giving different results:

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <type_traits>

using namespace std;

int main()
{
    vector<string> ar = {"mnciitbhu"};
    cout<<boolalpha;
    cout<<"First case : "<<endl;
    for(const auto& x : ar)
    {
        // Using std::remove_const and std::remove_reference
        // at the same time
        typedef typename std::remove_const<
            typename std::remove_reference<decltype(x)>::type>::type TT;
        cout<<std::is_same<std::string, TT>::value<<endl;
        cout<<std::is_same<const std::string, TT>::value<<endl;
        cout<<std::is_same<const std::string&, TT>::value<<endl;
    }
    cout<<endl;
    cout<<"Second case : "<<endl;
    for(const auto& x : ar)
    {
        // Same as above but the order of using std::remove_reference
        // and std::remove_const changed
        typedef typename std::remove_reference<
            typename std::remove_const<decltype(x)>::type>::type TT;
        cout<<std::is_same<std::string, TT>::value<<endl;
        cout<<std::is_same<const std::string, TT>::value<<endl;
        cout<<std::is_same<const std::string&, TT>::value<<endl;
    } 
    return 0;
}

The output is:

First case : 
true
false
false

Second case : 
false
true
false

Check on Coliru Viewer

My question is why does using std::remove_const and std::remove_reference in different order produce different results? Since I am removing both reference and const-ness, shouldn't the result be the same?

like image 862
0x6773 Avatar asked Jun 07 '15 05:06

0x6773


1 Answers

remove_const will only remove a top-level const qualifier, if one exists. In const std::string&, the const is not top-level, hence applying remove_const has no effect on it.

When you reverse the order and apply remove_reference first, the resulting type is const string; now the const is top-level and the subsequent application of remove_const will remove the const qualifier.

like image 141
Praetorian Avatar answered Oct 05 '22 23:10

Praetorian