Please consider the following code.
struct foo
{
};
template<typename T>
class test
{
public:
test() {}
const T& value() const
{
return f;
}
private:
T f;
};
int main()
{
const test<foo*> t;
foo* f = t.value();
return 0;
}
t is a const variable and value() is a constant member-function which returns const T&. AFAIK, a const type is not assignable to a non-const type. But how foo* f = t.value(); compiles well. How this is happening and how can I ensure value() can be only assigned to const foo*?
Edit
I found that, this is happening on when templates are used. Following code works as expected.
class test
{
public:
test() {}
const foo* value() const { return f; }
private:
foo* f;
};
int main()
{
const test t;
foo* f = t.value(); // error here
return 0;
}
Why the problem is happening when templates are used?
Because you have two levels of indirection – in your main function, that call to
valuereturns a reference to a const pointer to a non-constfoo.This can safely be copied into non-const pointer to a non-const
foo.If you’d instantiated
testwithconst foo *, it would be a different story.Update
From the comment:
Const data can only be read. It cannot be written (“mutated”). But copying some data is a way of reading it, so it’s okay. For example:
Here, I had some const data in
c, and I copied the data into a non-const variable n. That’s fine, it’s just reading the data. The value inchas not been modified.Now, suppose your
foohad some data in it:If I have a non-const pointer to one of those, I can modify the
nvalue through the pointer. You asked yourtesttemplate to store a pointer to a non-constfoo, and then made a const instance oftest. Only the pointer address is constant, therefore. No one can change the address stored in the pointer insidetest, so it cannot be made to point to another object. However, the object it points to can have its contents modified.Update 2:
When you made your non-template version of the example, you made a mistake. To get it right, you need to substitute
foo *into each place where there’s aT.Notice that you have a reference to a const
Tthere. So the return value will be a reference to something const: afoo *. It’s only the pointer address that can’t be modified. The object it points to can have its contents modified.In your second example, you got rid of the reference part, which changes the meaning and makes the
constmodifier apply to the object that the pointer points to, instead of applying to the pointer itself.