overloading with const

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>

using namespace std;

class myClass {
public:

	char get1stChange2nd(const char* pc) {
		char firstChar;
		cout << "version: const char* pc \n";
		firstChar = pc[0];
		//pc[1] = 'a';	//cannot assign to const
		pc++; //can modify but just a copy, won't change calling value
		return firstChar;}

	char get1stChange2nd(char* & pc) {
		char firstChar;
		cout << "version: char* pc \n";
		firstChar = pc[0];
		pc[1] = 'x';
		pc++;
		return firstChar;}

	char get1stChange2nd(char* const pc) { 
		char firstChar;
		cout << "version: char* const pc \n";
		firstChar = pc[0];
		pc[1] = 'z';
		//pc++;  //cannot assign to const
		return firstChar;}
};

int main()
{
	char myCharray[10];
	char returnChar;

	myClass mc1;
	strcpy(myCharray, "fghijk");
	char* const myCharrayConstPtr = myCharray;
	char* myCharrayRegPtr = myCharray;


	returnChar = mc1.get1stChange2nd("cannotModifyThis");
	printf("returnChar %c stringLiteral %s \n", returnChar, "cannotModifyThis");

	//??? ambiguous call to get...(char * const) or (char * &) ???
	//returnChar = mc1.get1stChange2nd(myCharrayRegPtr);
	//printf("returnChar %c myCharrayRegPtr %s \n", returnChar, myCharrayRegPtr);

	returnChar = mc1.get1stChange2nd(myCharrayConstPtr);
	printf("returnChar %c myCharrayConstPtr %s \n", returnChar, myCharrayConstPtr);

	return 0;
}


Since it is legal to overload parameters with const, I wanted to create 3 versions of a function taking a char* paramter.

version: const char* pc
The string cannot be modified but the pointer can be bumped

version: char* & pc
The string can be modified and the pointer can be bumped

version: char* const pc
The string can be modified but the pointer cannot be bumped

The 2 problems I have:

1. Line 13 yes it allows me to bump, but since pc is just a copy change is not returned. So I tried const char* & pc" but I got a bunch of errors on that. How do I return bumped pc yet retain const'ness of the string.

2. Line 47 through 49 I want to call the (char * &) version and change both the string and bump pointer. Why is the call ambiguous between (char * const) or (char * &) since the pointer is not const it shouldn't look at the (char * const) version?
1) const char*& is what you'd want in that case, from the sounds of it. The errors you were getting were probably ambiguity errors, just like your other problem. Although for this particular function, you probably just want char*& (no const qualifiers)

2) nonconst pointers like char* can be (and are) implicitly cast to const pointers like const char*. Therefore if you have the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
void func(char* a);        // "NC" version
void func(const char* a);  // "C" version

//-----------

const char* Cptr = "foobar";
char* NCptr = new char[10];

func(Cptr); // this is not ambiguous.  it will call the C version because a const pointer
            //  cannot be implicitly cast to a nonconst pointer

func(NCptr); // this, however, IS ambiguous, because the NCptr could fill either functions
             //  parameter requirements.  Therefore the compiler will error 


You're having this same problem, but is obfuscated by the addition of references, which compound ambiguity issues:

1
2
3
4
5
6
7
void func(int a);
void func(int& a);

//-------------------

int foo;
func(foo);   // ambiguous!  Could be calling either! 


You're sort of merging together these two ambiguity problems into one gigantic problem.


The easiest ways around this are any (or a combination) of the following:

1) give your functions different names
2) don't have nonconst (or const) overloads if you don't need them
3) do a better job of organizing


As it stands, if your function get1stChange2nd does what the name implies, you have the following:
- reads from the string buffer AND writes to it (char*, nonconst)
- needs to modify the passed pointer, so pass by reference (char*&)

Based on that criteria, I see no way to make this function do the appropriate job with any parameter type other than char*& (or a similar type like char**). Therefore that should be the only version of the function you have for this job, and you should remove the other ones, since they wouldn't work anyway (the const qualifier would not let them do their whole job).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

using namespace std;

void func(char* a) {cout << "NonConst Version\n"; }
void func(const char* a) {cout << "Const Version\n"; }

void func(int a) {cout << "func(int a)\n";}
void func(int& a) {cout << "func(int& a)\n";};


int main()
{
	const char* Cptr = "foobar";
	char* NCptr = new char[10];
	int foo = 9;
	const int foo2 = 7;

	cout << "call func(NCptr)\n";
	func(NCptr);
	cout << "call func(Cptr)\n";
	func(Cptr);

	//func(foo); ambiguous
	func(foo2);

	return 0;
}



call func(NCptr)
NonConst Version
call func(Cptr)
Const Version
func(int a)
Press any key to continue . . .


Thanks for the feedback Disch much appreciated. I can see what you mean about mixing up the reference '&' and the const overloads, when it's already pretty confusing just to have one of those overloads. Like you say, (char*&) would allow both to be changed, so I will keep that as the main function, and I think just to be stubborn I might keep the (const char *&) version too, then the function would handle string literals too. Guess 3 versions was just way too much. By the way, I don't know if this is compiler specific but I was not able to duplicate ambiguity with the func(Cptr), func(NCptr) functions, but perhaps this varies by compiler I am using VC++ 2008. In my case func(NCptr) called the NC version.


Anyways thanks a lot Disch!
I might've been wrong about that ambiguity. I didn't actually test it, heh. While the compiler might not find it ambiguous, the coder certainly would, so I'd still recommend you stay away from it.

In any event, glad I could help.
Topic archived. No new replies allowed.