void process( int boat ) { ; }
const void(*sequence_A[])( int ) = { process, process }; //ERROR
const void(**func_sequence)( int ) = sequence_A;
(*func_sequence++)( 7 );
Why won't this compile? I want const to refer to the array, not the contents of the array.
Error 1 error C2440: 'initializing' : cannot convert from 'void (__cdecl *)(int)' to 'const void (__cdecl *)(int)'
EDIT: So you guys are saying it doesn't exist. Fair enough. Just to be clear, I'm posting this analogy of the functionality I wanted but this is with int instead of function ptrs
//Compiles without error
int number1 = 7;
int number2 = 3;
const int* sequence_B[] = { &number1, &number2 };
const int** numbers = sequence_B;
int check = **numbers++; //value is 7
int chec2 = **numbers++; //value is 3
Okay, let's analyze the meaning of your statement
const void(*sequence_A[])( int ) = { process, process }; //ERROR
The way I remember the parsing of *x[] is that the second argument of main is char* argv[], so, it's an array of pointers. In other words, sequence_A is to be indexed, and then the result is to be dereferenced.
Then, to that you can apply a function call argument parenthesis with an int value, and as a result you should get a …
const void ?
Well that's not entirely meaningful. You can have a pointer to const void, but you can't dereference that pointer: you can't "get at" the const void directly. Yet here is some pointer to a function that produces as its expression value a const void.
To match that you would need
const void process( int boat ) { ; }
and although I haven't tried it, I doubt that any compiler will accept it. [Update: as it turns out, at least g++ accepts it, so it is one solution. But it's a very unconventional function signature. And not at all what you're after!]
In short, remove that const.
On a related note, as mentioned already in a comment you can't have a const raw array, except in the sense of a raw array of const items.
It's a corner case of the language, a problematic type system aberration inherited from C.
Along with the array type decay to pointer, also problematic.
Addendum: example of how to make the array items const:
void process( int boat ) { ; }
int main()
{
void(* const sequence_A[])( int ) = { process, process }; // OK
//sequence_A[0] = process; //ERROR
}
Related
I have a function (func1) that gets as a parameter a const pointer.
The value of this pointer is used for a second function (func2).
Depending on a boolean I want to modify this value before handing it to func2 or not. If I have to modify it I allocate new memory to store the modified version of it. Because in reality the const int pointer is a big array, I don't want to copy it.
I tried to solve it that way:
void func1(const int* value, bool change)
{
int* valueToUse;
if(change)
{
int changedValue = (*value)++;
valueToUse = &changedValue;
}
else
{
valueToUse = value; // <= here the Error occurs
}
func2(valueToUse);
}
void func2(const int* foo)
{
// ...
}
But if I do it this way, I get an error because I assign a const pointer to a simple pointer:
error: invalid conversion from 'const int* to int*'
Is there any easy way to solve this?
I can imagine a solution with two extra functions for each case or a version that calls func2 at two points. But because this presented code is only a very simplified version of my real code, I'm wandering if there is an easier solution to that.
Best would be a solution that works for C and C++.
Thanks guys in advance!
This works?
void func1(const int* value, bool change)
{
const int* valueToUse;
int changedValue;
if(change)
{
changedValue = (*value) + 1;
valueToUse = &changedValue;
}
else
{
valueToUse = value;
}
func2(valueToUse);
}
A const int* is a pointer to const int, which is not a const pointer to int. Therefore the pointer itself is free to change.
Also, incrementing (*value) is an error because *value is a const int.
In func1, you can make 2 calls to func2, this way there is no copy when not needed and the original value is never changed:
void func1(const int* value, bool change)
{
if(change)
{
int changedValue = *value+1;
func2(&changedValue);
}
else
{
func2(value);
}
}
void func1(const int* value, int change)
{
int* valueToUse;
if(change)
{
(*(int*)value)++;
valueToUse = (int*)value;
}
else
{
valueToUse = (int*)value; // <= here the Error occurs
}
func2(valueToUse);
}
But you don't really need this valueToUse, it's what i think, so.
void func1(const int* value, int change)
{
if(change)
(*(int*)value)++;
func2(value);
}
const int* value
This means pointer to a constant int value. It is not permitted to change the value of a constant int.
There are two ways of solving this.
Change signature of first function void func1(int* value, bool change)
Pass arguments to func1 after constant casting using const_cast and change
int changedValue = (*value)++; to int changedValue = *value + 1;
Well, running this code i receive just a warning, though i think that type conversion will help you.
valueToUse = (int*)value;
I have two functions with a little different functionality, so I can't make them as template functions.
int func64(__int64 a) {
return (int) a/2;
}
int func32(int a) {
return a--;
}
Depending on variable b64, I would like to call func64 or func32. I don't want check if b64 is true many times in my code, so I use pointers to functions.
void do_func(bool b64) {
typedef int (*pfunc32)(int);
typedef int (*pfunc64)(__int64);
pfunc32 call_func;
if (b64)
call_func = func64; //error C2440: '=' : cannot convert from 'int (__cdecl *)(__int64)' to 'pfunc32'
else
call_func = func32;
//...
call_func(6);
}
How can I avoid this error and cast call_func to pfunc32 or pfunc64?
The language requires all functions called through the same function pointer to have the same prototype.
Depending on what you want to achieve, you could use the pointer/cast aproach already mentioned (which satisfies this requirement at the loss of type safety) or pass a union instead:
union u32_64
{
__int64 i64;
int i32;
};
int func64(union u32_64 a) {
return (int) a.i64/2;
}
int func32(union u32_64 a) {
return --a.i32;
}
void do_func(bool b64) {
typedef int (*pfunc)(union u32_64);
pfunc call_func;
if (b64)
call_func = func64;
else
call_func = func32;
//...
union u32_64 u = { .i64 = 6 };
call_func(u);
}
Pass a void pointer and cast it in the function body.
Of course this means less compiler control if you use the wrong type; if you call func64 and pass an int to it the program will compile and produce wrong results without giving you any tip of what is going wrong.
int func64(void *a) {
__int64 b = *((__int64*) a);
return (int) b/2;
}
int func32(void *a) {
int b = *((int *) a)
return b-1;
}
I need to call func32() or func64() depending on flag b64
So do that:
void do_func(bool b64) {
if (b64)
func64(6);
else
func32(6);
}
Well, first of all, please note that function func32 is returning the input argument as is.
This is because with return a--, you are returning the value of a before decrementing it.
Perhaps you meant to return a-1 instead?
In any case, you can simply declare this function as int func32(__int64 a).
This way, it will have the same prototype as function func64, but will work exactly as before.
BTW, calling a function through a pointer might be more "expensive" than a simple branch operation, so depending on your application, you might be better off with a simple if/else conditional statement...
Make a wrapper for func64:
int func64_as_32(int a) {
return func64(a);
}
Now you can assign either func32 or func64_as_32 to call_func since they have the same signature. The value you pass in, 6, has type int so passing it to func64_as_32 has the same effect as passing it directly to func64.
If you have call sites where you pass in a value of type __int64 then you'd do it the other way around, wrap func32.
As bool in C++ converts to int ( true => 1, false => 0 ) you can use b64 as array index. So take SJuan76's advice, convert your functions prototype to int f(void*) and put them into array int (*array_fun[2])(void* x); . You can call these functions then like that :
int p = 6;
array_fun[b64](&p);
I have a method with the prototype:
bool getAssignment(const Query& query, Assignment *&result);
I am a bit confused about the type of the second param (Assignment *&result) since I don't think I have seen something like that before. It is used like:
Assignment *a;
if (!getAssignment(query, a))
return false;
Is it a reference to a pointer or the other way around ? or neither ? Any explanation is appreciated. Thanks.
It's a reference to a pointer. The idea is to be able to change the pointer. It's like any other type.
Detailed explanation and example:
void f( char* p )
{
p = new char[ 100 ];
}
int main()
{
char* p_main = NULL;
f( p_main );
return 0;
}
will not change p_main to point to the allocated char array (it's a definite memory leak). This is because you copy the pointer, it's passed by value (it's like passing an int by value; for example void f( int x ) != void f( int& x ) ) .
So, if you change f:
void f( char*& p )
now, this will pass p_main by reference and will change it. Thus, this is not a memory leak and after the execution of f, p_main will correctly point to the allocated memory.
P.S. The same can be done, by using double pointer (as, for example, C does not have references):
void f( char** p )
{
*p = new char[ 100 ];
}
int main()
{
char* p_main = NULL;
f( &p_main );
return 0;
}
For something like this, you basically read the declaration from right to left (or inside out).
In other words, you want to start from the name of the item being declared, then progress outward. In this case, progressing directly from the name to the type, we get:
I understand that a const pointer can be declared a couple ways:
const int * intPtr1; // Declares a pointer that cannot be changed.
int * const intPtr2; // Declares a pointer whose contents cannot be changed.
// EDIT: THE ABOVE CLAIMS ARE INCORRECT, PLEASE READ THE ANSWERS.
But what about the same principles within the context of function arguments?
I would assume that the following is redundant:
void someFunc1(const int * arg);
void someFunc2(int * arg);
Since someFunc 1 and 2 do a pass-by-value for the pointer itself, its impossible for someFunc1 to change the value of the original pointer, in a given call to the function. To illustrate:
int i = 5;
int * iPtr = &i;
someFunc1(iPtr); // The value of iPtr is copied in and thus cannot be changed by someFunc1.
If these are true, then there is no point in ever declaring a function with a 'const int * ptr' type arg, correct?
You have it backwards:
const int * intPtr1; // Declares a pointer whose contents cannot be changed.
int * const intPtr2; // Declares a pointer that cannot be changed.
The following const is indeed unnecessary, and there's no reason to put it in a function declaration:
void someFunc1(int * const arg);
However, you might want to put it in the function implementation, for the same reason that you might want to declare a local variable (or anything else) const - the implementation may be easier to follow when you know that certain things won't change. You can do that whether or not it's declared const in any other declarations of the function.
Well it is not meant for the caller but for the code inside the someFunc1. So that any code inside someFunc1 wont accidentally change it. like
void someFunc1(int *arg) {
int i = 9;
arg = &i; // here is the issue
int j = *arg;
}
Lets do some case study:
1) Just making the pointed value const
void someFunc1(const int * arg) {
int i = 9;
*arg = i; // <- compiler error as pointed value is const
}
2) Just making the pointer const
void someFunc1(int * const arg) {
int i = 9;
arg = &i; // <- compiler error as pointer is const
}
3) Right way to use const if variables involved can be const:
void someFunc1(const int * const arg) {
int i = 9;
*arg = i; // <- compiler error as pointed value is const
arg = &i; // <- compiler error as pointer is const
}
This should clear all doubts. So I already mentioned it is meant for the function code and not for the caller and you should use the most restrictive of the 3 cases i mentioned above.
EDIT:
Even in declarations of functions its a good practice to declare const. This will not only increase readability but also the caller will be aware of the contract and has more confidence regarding immutability of arguments. (This is required bcoz you generally share your header files so caller might not have your implementation c/cpp file)
Even compiler can point out better if both declaration and definitions are in sync.
You've got your logic the wrong way round. You should read the type backwards, so const int * is a pointer to a const int and int * const is a const pointer to an int.
Example:
void foo() {
int a = 0;
int b = 0;
int * const ptrA = &a;
*ptrA = 1;
ptrA = &b; ///< Error
const int * ptrB = &a;
*ptrB = 1; ///< Error
ptrB = &b;
const int * const ptrC = &a;
*ptrC = 1; ///< Error
ptrC = &a; ///< Error
}
To elaborate and show why you would want your function parameter to be a const int * you might want to indicate to the caller that they must pass in an int because you as a function want to change the value. Consider this code for instance:
void someFunc1(const int * arg) {
// Can't change *arg in here
}
void someFunc2(int * arg) {
*arg = 5;
}
void foo() {
int a = 0;
someFunc1(&a);
someFunc2(&a);
const int b = 0;
someFunc1(&b);
someFunc2(&b); ///< *** Error here. Must pass in an int not a const int.
}
Yes, you are correct (ignoring the fact that you got them the wrong way around)- there is no sense in taking non-reference const parameters. In addition, there is no sense in returning non-reference const values.
You have it the wrong way:
const int * intPtr1; // Declares a pointer whose contents cannot be changed.
int * const intPtr2; // Declares a pointer that cannot be changed.
Generally speaking its easier to reason about constness when writting that expression slightly different: const int* is the same type as int const *. In that notation the rules are much clearer, const always applies to the type preceding it, therefore:
int const * intPtr1; // Declares a pointer to const int.
int * const intPtr2; // Declares a const pointer to int.
int const * * const * complexPtr; // A pointer to const pointer to pointer to const int
When the type is written with a leading const, the const is handled as if it was written after the first type, so const T* becomes T const *.
void someFunc2(int * arg);
Is therefore not redundant, since someFunc2 may change the contents of arg, while someFunc1 may not. void someFunc3(int * const arg); would be redundant (and ambigous) though
Suppose I have a class:
class test {
public:
void print();
private:
int x;
};
void test::print()
{
cout<< this->x;
}
and I have these variable definitions:
test object1;
test object2;
When I call object1.print() this happens to store address of object1 and so I get x from object1 printed and when I call object2.print() this happens to store address of object2 and I get x from object2 printed. How does it happen?
Each non-static member function has an implicit hidden "current object" parameter that is exposed to you as this pointer.
So you can think that for
test::print();
there's some
test_print( test* this );
global function and so when you write
objectX.print();
in your code the compiler inserts a call to
test_print(&objectX);
and this way the member function knows the address of "the current" object.
You can think of the this pointer being an implicit argument to the functions. Imagine a little class like
class C {
public:
C( int x ) : m_x( x ) { }
void increment( int value ) {
m_x += value; // same as 'this->m_x += value'
}
int multiply( int times ) const {
return m_x * times; // same as 'return this->m_x * times;'
}
private:
int m_x;
};
which allows you to write code like
C two( 2 );
two.increment( 2 );
int result = two.multiply( 3 );
Now, what's actually happening is that the member functions increment and multiply are called with an extra pointer argument, pointing to the object on which the function is invoked. This pointer is known as this inside the method. The type of the this pointer is different, depending on whether the method is const (as multiply is) or not (as is the case with increment).
You can do something like it yourself as well, consider:
class C {
public:
C( int x ) : m_x( x ) { }
void increment( C * const that, int value ) {
that->m_x += value;
}
int multiply( C const * const that, int times ) const {
return that->m_x * times;
}
private:
int m_x;
};
you could write code like
C two( 2 );
two.increment( &two, 2 );
int result = two.multiply( &two, 3 );
Notice that the type of the this pointer is C const * const for the multiply function, so both the pointer itself is const but also the object being pointed to! This is why you cannot change member variables inside a const method - the this pointer has a type which forbids it. This could be resolved using the mutable keyword (I don't want to get side-tracked too far, so I'll rather not explain how that works) but even using a const_cast:
int C::multiply( int times ) const {
C * const that = const_cast<C * const>( this );
that->m_x = 0; // evil! Can modify member variable because const'ness was casted away
// ..
}
I'm mentioning this since it demonstrates that this isn't as special a pointer as it may seem, and this particular hack is often a better solution than making a member variable mutable since this hack is local to one function whereas mutable makes the variable mutable for all const methods of the class.
The way to think about it is that this is simply a pointer to the memory for whichever object you're currently working with. So if you do obj1.print(), then this = &obj1;. If you do obj2.print(), then this = &obj2;.
this has different values for different objects
Each instance of class test gets it's own copy of member variable x. Since x is unique for each instance, the value can be anything you want it to be.
The variable this, refers to the instance to which it is associated. You don't have to use the variable 'this'. You could just write:
void test::print()
{
cout << x;
}