This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
why isnt it legal to convert (pointer to pointer to non-const) to a (pointer to pointer to a const)
I have a function:
bool isCirclePolygonIntersection(const Point*, const int*, const Point*,
const Point**, const int*);
and I'm trying to call it like this:
isCirclePolygonIntersection(p, &r, poly_coord, poly, &poly_size)
where poly defined like this:
Point** poly = new Point*[poly_size];
and there is a compiler error when I'm trying to compile it:
error C2664: 'isCirclePolygonIntersection' : cannot convert parameter 4 from 'Point **' to 'const Point **'
1> Conversion loses qualifiers
from what I've learned is that you cannot give const argument to function when a function expects a non const argument, but it's fine otherwise.
Does anyone knows what is the problem??
Thanks.
You're correct; you can implicitly convert a T * to a const T *. However, you cannot implicitly convert a T ** to a const T **. See this from the C FAQ: http://c-faq.com/ansi/constmismatch.html.
An implicit conversion from Point** to const Point** would open a hole in the type system, hence there is no such conversion in C++.
For details, see Why am I getting an error converting a Foo** → Foo const**?
Changing const Point** to const Point * const * will fix your problem.
By the way, why the additional indirection? That is, why do you use an array of pointers? I would suggest a std::vector<Point> instead. Or is Point a polymorphic base class?
Parashift has a great explanation on why this is prohibited:
http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17
Related
This question already has answers here:
What is the difference between const int*, const int * const, and int const *?
(23 answers)
Closed 3 years ago.
I'm writing a code with following function and new to C++
foo(void const *pCluster, const uint32_t fieldNum, __attribute__((unused)) const uint32_t subFieldNum, const int64_t value)
{
bool status = false;
mycustomStruct* const pFlmcCtrl = static_cast<mycustomStruct* const>(pMdbCluster);
// Some Processing
}
This gives error error: static_cast from 'const void *' to 'mycustomStruct* const' casts away qualifiers.
Please help me understand the error here. I could not understand
This
T const* p
is a pointer to a const T. This
T* const p
is a const pointer to a T. Notice the difference? In the first example, the thing the pointer points to is the thing that is const. In the second example, the pointer itself is the thing that is const. Attempting to cast a void const* to a mycustomStruct* const means casting a pointer that points to something that is const to a pointer that points to something that is not const (just the pointer itself happens to be const). Thus, this cast would drop a const qualifier, which is not something that static_cast can do…
You probably wanted to write
const mycustomStruct* pFlmcCtrl = static_cast<const mycustomStruct*>(pMdbCluster);
I have a function that receives float** as an argument, and I tried to change it to take const float**.
The compiler (g++) didn't like it and issued :
invalid conversion from ‘float**’ to ‘const float**’
this makes no sense to me, I know (and verified) that I can pass char* to a function that takes const char*, so why not with const float**?
See Why am I getting an error converting a Foo** → const Foo**?
Because converting Foo** → const Foo** would be invalid and dangerous ... The reason the conversion from Foo** → const Foo** is dangerous is that it would let you silently and accidentally modify a const Foo object without a cast
The reference goes on to give an example of how such an implicit conversion could allow me one to modify a const object without a cast.
This is a very tricky restriction. It is related to the aliasing rules of the language. Take a look at what the standards say, because I have faced this once before:
(Page 61)
[Note: if a program could assign a
pointer of type T** to a pointer of
type const T** (that is, if line //1
below was allowed), a program could
inadvertently modify a const object
(as it is done on line //2). For
example,
int main() {
const char c = 'c';
char* pc;
const char** pcc = &pc; //1: not allowed
*pcc = &c;
*pc = 'C'; //2: modifies a const object
}
—end note]
Other anwers have detailled why this is an error in C++.
Let me address the question behind your question. You wanted to state, in the interface of your function, that your function will not modify float values contained in the array. Nice intention, and enables that your function is called with const float ** arrays. The question behind your question would be, how to achieve this without resolving to ugly casts.
The correct way to achieve what you wanted is to change the type of your function parameter to const float * const *.
The additional const between the stars assures the compiler that your method will not try to store pointers to const float in the array, since this type declares that the pointer values are also const.
You can now call this function with float ** (which was the example in your question), const float **, and const float * const * arguments.
If you converted the parameter to const float** you could then store a const float* at the memory location where the parameter points to. But the calling function thinks that this memory location is supposed to contain a non-const float* and might later try to change this pointed-to float.
Therefore you cannot cast a float** to a const float**, it would allow you to store pointers to constants in locations where pointers to mutable values are expected.
For more details see the C++ FAQ Lite.
This question already has answers here:
Cannot convert from XXX** to const XXX** [duplicate]
(3 answers)
How to convert "pointer to pointer type" to const?
(2 answers)
Closed 4 years ago.
E.g. the following will fail to compile:
auto foo = [](const char**) {};
char* ptr = nullptr;
foo(&ptr);
Visual studio says that there's a conversion that loses qualifiers. Clang says cannot initialize a parameter of type 'const char **' with an rvalue of type 'char **". Perhaps my brain just isn't working today, but why is this dis-allowed? char* can implicitly convert to const char* after all
Oh wait, yes my brain isn't working today. foo can assign a const char* to the pointer, which is clearly bad.
This question already has answers here:
Why isn't it legal to convert "pointer to pointer to non-const" to a "pointer to pointer to const"
(5 answers)
Closed 7 years ago.
I know that const char * p means we can't change the value which is pointed by p through p.
Now I'm writing a function which will take the parameters of the function main. Meaning that this function will take a char **. So I write this function like this:
void func(const char **);.
But when I pass the parameter of main to it, I get an error:
error C2664: 'void func(const char **)' : cannot convert argument 1 from 'char **' to 'const char **'
I just want to initialize a const pointer with a non-const pointer. This should work. If we do the opposite thing, we should get some error. But now I don't know why I get this error.
I just want to initialize a const pointer with a non-const pointer. This should be work.
That's not what you're trying to do, no.
You're trying to initialise a non-const pointer to pointer to const char, with a non-const pointer to pointer to char. That is never performed implicitly. Why? It's well documented elsewhere because it's not completely intuitive to all but, in short, if converting char** to const char** were allowed, then const-correctness would be violated.
It's not the same as converting char** to char** const, which is what you think you're trying to do.
It's unfortunate that main's arguments do not already have const strewn about them. Sorry. Fortunately, you can work around it with a const_cast:
void foo(const char** argv) {}
int main(int argc, char** argv)
{
foo(const_cast<const char**>(argv));
}
This is one of those situations in which using const_cast to hack around pre-existing silliness, contrary to the wishes of the type system, is actually okay.
I have a function that receives float** as an argument, and I tried to change it to take const float**.
The compiler (g++) didn't like it and issued :
invalid conversion from ‘float**’ to ‘const float**’
this makes no sense to me, I know (and verified) that I can pass char* to a function that takes const char*, so why not with const float**?
See Why am I getting an error converting a Foo** → const Foo**?
Because converting Foo** → const Foo** would be invalid and dangerous ... The reason the conversion from Foo** → const Foo** is dangerous is that it would let you silently and accidentally modify a const Foo object without a cast
The reference goes on to give an example of how such an implicit conversion could allow me one to modify a const object without a cast.
This is a very tricky restriction. It is related to the aliasing rules of the language. Take a look at what the standards say, because I have faced this once before:
(Page 61)
[Note: if a program could assign a
pointer of type T** to a pointer of
type const T** (that is, if line //1
below was allowed), a program could
inadvertently modify a const object
(as it is done on line //2). For
example,
int main() {
const char c = 'c';
char* pc;
const char** pcc = &pc; //1: not allowed
*pcc = &c;
*pc = 'C'; //2: modifies a const object
}
—end note]
Other anwers have detailled why this is an error in C++.
Let me address the question behind your question. You wanted to state, in the interface of your function, that your function will not modify float values contained in the array. Nice intention, and enables that your function is called with const float ** arrays. The question behind your question would be, how to achieve this without resolving to ugly casts.
The correct way to achieve what you wanted is to change the type of your function parameter to const float * const *.
The additional const between the stars assures the compiler that your method will not try to store pointers to const float in the array, since this type declares that the pointer values are also const.
You can now call this function with float ** (which was the example in your question), const float **, and const float * const * arguments.
If you converted the parameter to const float** you could then store a const float* at the memory location where the parameter points to. But the calling function thinks that this memory location is supposed to contain a non-const float* and might later try to change this pointed-to float.
Therefore you cannot cast a float** to a const float**, it would allow you to store pointers to constants in locations where pointers to mutable values are expected.
For more details see the C++ FAQ Lite.