18

With the following code

void TestF(const double ** testv){;}
void callTest(){
    double** test;
    TestF(test);
}

I get this:

'TestF' : cannot convert parameter 1 from 'double **' to 'const double **'

I cannot understand why. Why test cannot be silently casted to const double**? Why should I do it explicitly? I know that

TestF(const_cast<const double**>(test)) 

makes my code correct, but I feel this should be unnecessary.

Are there some key concepts about const that I'm missing?

abyss.7
  • 13,882
  • 11
  • 56
  • 100
jimifiki
  • 5,377
  • 2
  • 34
  • 60
  • 4
    The issue has been covered many times here, but here's a FAQ entry dedicated to this very question http://www.parashift.com/c++-faq/constptrptr-conversion.html – AnT stands with Russia Nov 11 '13 at 15:49
  • http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-int-const – Marius Bancila Nov 11 '13 at 15:53
  • possible duplicate of [constness and pointers to pointers](http://stackoverflow.com/questions/14441979/constness-and-pointers-to-pointers) – AnT stands with Russia Nov 11 '13 at 15:57
  • 2
    There is **no cast** in the first block of code. There is an **implicit conversion**, and the various answers explain why that **conversion** is not legal. – Pete Becker Nov 11 '13 at 16:00

2 Answers2

13

The language allows implicit conversion from double ** to const double *const *, but not to const double **. The conversion you attempt would implicitly violate the rules of const correctness, even though it is not immediately obvious.

The example in the [de-facto standard] C++ FAQ illustrates the issue

https://isocpp.org/wiki/faq/const-correctness#constptrptr-conversion

Basically, the rule is: once you add const at some level of indirection, you have to add const to all levels of indirection all the way to the right. For example, int ***** cannot be implicitly converted to int **const ***, but it can be implicitly converted to int **const *const *const *

JSQuareD
  • 4,641
  • 2
  • 18
  • 27
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
11

It is correct that a double ** cannot be implicitly converted to a const double **. It can be converted to a const double * const *, though.

Imagine this scenario:

const double cd = 7.0;
double d = 4.0;
double *pd = &d;
double **ppd = &pd;
const double **ppCd = ppd;  //this is illegal, but if it were possible:
*ppCd = &cd;  //now *ppCd, which is also *ppd, which is pd, points to cd
*pd = 3.14; // pd now points to cd and thus modifies a const value!

So, if your function does not intend to modify any of the pointers involved, change it to take a const double * const *. If it intends to do modifications, you must decide whether all the modifications it does are safe and thus const_cast can be used, or whether you really need to pass in a const double **.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455