Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialising a reference in a const object

I have the following code:

class c_int {
public:
  int &i;
  c_int(int &in) : i(in) {
  };
  c_int(const int &in) : i(in) {
  };
};


int main (void) {

  const int i = 10;
  const c_int c(i); 

  std::cout << c.i << std::endl;

  return 0;
}

Compiling it gives the following error message:

tmp.cpp:12:30: error: invalid initialization of reference of type 'int&' from ex
presion of type 'const int'

I am having a bit of trouble, figuring out how to get this to work, how should I initialize a reference inside a const object?

Edit: Ideally I would like this object to serve for non-const ints too; when the object is not declared const.

Further Edit:

I wish to use the object like this also:

int main (void) {

  int i = 10;
  c_int c(i); // for some reason this calls the 2nd of my constructors, does name mangling not take const into account?
  c.i = 9;    

  std::cout << i << std::endl;

  return 0;
}
like image 780
jayjay Avatar asked Sep 22 '26 12:09

jayjay


2 Answers

The problem is not that your object is const : it is that you are trying to bind a const reference to a non-const one : this is illegal.

You can bind a const reference to a const member :

class c_int {
public:
  const int &j;
  c_int(const int &in) : j(in){  };
};


int main (void) {

  const int i = 10;
  c_int c(i); 

  std::cout << c.j << std::endl;
}

You can still uses two different classes for const and non const objects, or if you really need a single class and know what you are doing, use a const_cast (really discouraged : any attempt to modify the object will be undefined behavior) :

class c_int {
public:
  int& i;
  c_int(int& in) : i(in){ }
  c_int(const int& in) : i(const_cast<int&>(in)){ } // Very wrong
};

Or, forget about passing by reference and use value semantics :

class c_int {
public:
  int i;
  c_int(int in) : i(in){ }
};

Edit:

You can still add a constructor taking a non-const reference for cases where your int argument is not const :

class c_int {
public:
  const int &j;
  c_int(const int &in) : j(in){  };
  c_int(int &in) : j(in){ }
};


int main (void) {

  const int i = 10;
  const c_int c(i); 
  std::cout << c.j << '\n';

  int i2 = 11;
  const c_int d(i2); 
  std::cout << d.j << '\n';  
}

Live demo.

like image 114
quantdev Avatar answered Sep 24 '26 06:09

quantdev


I would suggest you have two different classes. One which holds a const reference, and one which holds a non-const reference. This is similar to the way standard containers have both iterator and const_iterator as two seperate classes.

class c_int {
public:
  int &i;
  c_int(int &in) : i(in) {};
};

class const_c_int {
public:
  int const &i;
  c_int(int const &in) : i(in) {};
};

If you want to avoid repeating code, you could make a template:

template<typename T>
class c_generic {
public:
  T& i;
  c_generic(T& in) :i(in) {}
};

typedef c_generic<int> c_int;
typedef c_generic<int const> const_c_int;
like image 43
Benjamin Lindley Avatar answered Sep 24 '26 04:09

Benjamin Lindley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!