Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

const_reference_type not compiling but const value_type& compiling

Tags:

c++

gcc

constants

#include <iostream>

template <typename T>
struct ref_exp{
    typedef T value_type;
    typedef value_type& reference_type;
    typedef const reference_type const_reference_type;

    ref_exp(value_type data): _data(data){}
    const_reference_type data() const {return _data;}
  private:
    value_type _data;
};

int main(){
    ref_exp<int> exp1(2);
    std::cout << exp1.data() << std::endl;

    return 0;
}

The above code doesn't compile

ref.cpp: In member function ‘T& ref_exp<T>::data() const [with T = int]’:
ref.cpp:17:   instantiated from here
ref.cpp:10: error: invalid initialization of reference of type ‘int&’ from expression of type ‘const int’

But If I replace const_reference_type data() const with const value_type& data() const it works. Also If I replace typedef const reference_type const_reference_type
with typedef const value_type& const_reference_type it compiles

like image 350
Neel Basu Avatar asked Dec 08 '22 18:12

Neel Basu


2 Answers

Your const_reference_type typedef does not do what you think:

typedef const reference_type const_reference_type;

const_reference_type is int& const - that is, the entire type reference_type has const applied to it - and a const reference cannot exist, so you get int&. You are not getting a const int& as you are expecting.

As you've noted, the fix here is to do:

typedef const value_type& const_reference_type;

The tip here is to not think of typedef as just a find-and-replace of type names, because it doesn't behave that way.

like image 194
Joseph Mansfield Avatar answered Dec 11 '22 12:12

Joseph Mansfield


const reference_type is indicating that the reference is const, not that the referenced object is const.

typedef int &int_ref;  // int_ref is a reference to a non-const int
typedef const int_ref int_ref_const; 
     // int_ref_const is a const reference to a non-const int

The const qualifier in the second case is basically a no-op, since references are implicitly const.

Think about a similar case with pointers:

typedef int *int_ptr; // int_ptr is a pointer to a non-const int
typedef const int_ptr int_ptr_const; 
    // int_ptr_const is a const pointer to a non-const int.
like image 28
Vaughn Cato Avatar answered Dec 11 '22 11:12

Vaughn Cato