Как преобразовать "указатель на тип указателя" в const?

Со следующим кодом

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

Я получаю это:

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

Я не понимаю, почему. Почему test не может быть беззвучно нажата на const double**? Почему я должен делать это явно? Я знаю, что

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

делает мой код правильным, но я считаю, что это не нужно.

Есть ли какие-то ключевые понятия о const, которые мне не хватает?

Ответ 1

Язык позволяет неявное преобразование от double ** до const double *const *, но не к const double **. Преобразование, которое вы пытаетесь, будет неявно нарушать правила корректности const, даже если это не сразу очевидно.

Пример в стандарте [de facto standard] С++ иллюстрирует проблему

http://www.parashift.com/c++-faq/constptrptr-conversion.html

В принципе, правило: после добавления const на некоторый уровень косвенности, вы должны добавить const на все уровни косвенности до упора вправо. Например, int ***** не может быть неявно преобразован в int **const ***, но он может быть неявно преобразован в int **const *const *const *

Ответ 2

Верно, что a double ** не может быть неявно преобразован в const double **. Однако он может быть преобразован в const double * const *.

Представьте себе этот сценарий:

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!

Итак, если ваша функция не намерена изменять какой-либо из указателей, измените ее, чтобы взять const double * const *. Если он намеревается внести изменения, вы должны решить, безопасны ли все его модификации и, следовательно, const_cast, или вам действительно нужно передать const double **.