{"id":463,"date":"2009-12-05T15:16:01","date_gmt":"2009-12-05T15:16:01","guid":{"rendered":"http:\/\/kera.name\/articles\/?p=463"},"modified":"2011-06-22T09:28:28","modified_gmt":"2011-06-22T09:28:28","slug":"a-question-on-indirect-constness","status":"publish","type":"post","link":"https:\/\/kera.name\/articles\/2009\/12\/a-question-on-indirect-constness\/","title":{"rendered":"A Question On Indirect Constness"},"content":{"rendered":"<p>You may have used code such as [1]:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">int<em> a = f();\nconst int<\/em> b = a;\ng(b);<\/p>\n<p>\/\/ Success<\/textarea>\n<\/p>\n<p>Here we obtain a pointer <code>b<\/code> to the same object that <code>a<\/code> points to, but we say that it is now immutable (through b, at least).<\/p>\n<p>However, C++ does not allow a programmer to add <code>const<\/code>ness more than one layer of indirection away [2]:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">int<strong> a = f();\nconst int<\/strong> b = a;\ng(b);<\/p>\n<p>\/\/ error: invalid conversion from 'int<strong>' to 'const int<\/strong>'<\/textarea>\n<\/p>\n<p>Of course, you can still make the pointer itself <code>const<\/code> [3]:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">int<strong> a = f();\nint<\/strong> const b = a;\ng(b);<\/p>\n<p>\/\/ Success<\/textarea>\n<\/p>\n<p>So it turns out that you can add <code>const<\/code>ness to the pointer [3], or to the immediate pointee [1], but you can&#039;t add <code>const<\/code>ness to the pointee of the pointee [2].<\/p>\n<p>The question is: why not? How does <em>adding<\/em> <code>const<\/code>ness violate <code>const<\/code>-correctness? Answers on a postcard, please.<\/p>\n<hr>\n<p><b>Update:<\/b> As Kniht correctly pointed out in the comments (and, in fact, as the standard itself explains in a note), this is invalid for very good reason:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\"><\/p>\n<h1>include <cassert><\/h1>\n<p>int main() {\nchar* p = 0;<\/p>\n<p>\/\/char const<strong> a = &p; \/\/ not allowed, but let's pretend it is\nchar const<\/strong> a = (char const**)&p; \/\/ instead force the cast to compile<\/p>\n<p>char const<em> orig = \"original\";\n<\/em>a = orig; \/\/ type of <em>a is char const<\/em>, which is the type of orig, this is allowed<\/p>\n<p>assert(p == orig); \/\/ oops! char<em> points to a char const<\/em>\n}\n<\/textarea><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Why does C++ not allow conversion from <code>T**<\/code> to <code>T const**<\/code>?<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[21,20],"_links":{"self":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/463"}],"collection":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/comments?post=463"}],"version-history":[{"count":6,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/463\/revisions"}],"predecessor-version":[{"id":724,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/463\/revisions\/724"}],"wp:attachment":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/media?parent=463"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/categories?post=463"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/tags?post=463"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}