D
Dan Katz
Hi -
I'm trying to understand how function overloading interacts with
variable argument lists in C++, and I'm not getting much clarity.
In detail, I have some code which tries to overload a function with a
variable argument list:
------------------------------------------------------------------------
#include <iostream>
#include <stdarg.h> //vsprintf, va_list, va_start, va_end
using std::cout;
using std::endl;
void fun1(const char* extra, const char* format, va_list ap) {
char outString[100];
vsprintf(outString, format, ap);
cout << extra << outString << endl;
}
void fun1(const char* format, ...) {
va_list ap;
va_start(ap, format);
fun1("Extra: ", format, ap);
va_end(ap);
}
int main()
{
const char* format1 = "The format string with 1 param -- %s";
const char* format2 = "The format string with 2 params -- %s and %s";
const char* format3 = "The format string with 3 params -- %s and %s and %s";
const char* arg1 = "arg1";
const char* arg2 = "arg2";
const char* arg3 = "arg3";
fun1(format1, arg1);
fun1(format2, arg1, arg2);
fun1(format2, "arg1", "arg2");
fun1(format3, arg1, arg2, arg3);
return 0;
}
------------------------------------------------------------------------
and when I run this program I get the following:
------------------------------------------------------------------------
$ g++ --version
g++ (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)
[... copyright stuff elided ...]
$ g++ -Wall -W -ansi val_list_test_overload.cc
val_list_test_overload.cc: In function 'int main()':
val_list_test_overload.cc:32: warning: deprecated conversion from string constant to 'char*'
$ ./a.out
Extra: The format string with 1 param -- arg1
Extra: The format string with 2 params -- arg1 and arg2
The format string with 2 params -- %s and %sarg1
Extra: The format string with 3 params -- arg1 and arg2 and arg3
------------------------------------------------------------------------
I guess my questions are:
1) It appears that g++ considers the va_list type to be a (non-const)
char*. Is this normal? Is it standards compliant? (I didn't see
anything in the standard that would require it, but I am not a
language lawyer...)
2) It seems that the compiler is treating string literals differently
from variables which have been defined to be of type "const char*" --
i.e. in the two invocations of fun1 with the format2 string. In
particular, it seems to be doing an implicit conversion from string
constant to char*, but not from declared "const char*" to char*. But
I was under the impression that a string literal is in fact a "const
char*". Is there something in the standard that allows them to be
treated differently in this context?
3) Assuming that g++ is being standards compliant, is can anyone suggest
a better (portable, standards compliant) way to ensure that
fun1(format2, "arg1", "arg2")
ends up calling the
void fun1(const char* format, ...)
version of fun1?
Thanks!
Dan
I'm trying to understand how function overloading interacts with
variable argument lists in C++, and I'm not getting much clarity.
In detail, I have some code which tries to overload a function with a
variable argument list:
------------------------------------------------------------------------
#include <iostream>
#include <stdarg.h> //vsprintf, va_list, va_start, va_end
using std::cout;
using std::endl;
void fun1(const char* extra, const char* format, va_list ap) {
char outString[100];
vsprintf(outString, format, ap);
cout << extra << outString << endl;
}
void fun1(const char* format, ...) {
va_list ap;
va_start(ap, format);
fun1("Extra: ", format, ap);
va_end(ap);
}
int main()
{
const char* format1 = "The format string with 1 param -- %s";
const char* format2 = "The format string with 2 params -- %s and %s";
const char* format3 = "The format string with 3 params -- %s and %s and %s";
const char* arg1 = "arg1";
const char* arg2 = "arg2";
const char* arg3 = "arg3";
fun1(format1, arg1);
fun1(format2, arg1, arg2);
fun1(format2, "arg1", "arg2");
fun1(format3, arg1, arg2, arg3);
return 0;
}
------------------------------------------------------------------------
and when I run this program I get the following:
------------------------------------------------------------------------
$ g++ --version
g++ (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)
[... copyright stuff elided ...]
$ g++ -Wall -W -ansi val_list_test_overload.cc
val_list_test_overload.cc: In function 'int main()':
val_list_test_overload.cc:32: warning: deprecated conversion from string constant to 'char*'
$ ./a.out
Extra: The format string with 1 param -- arg1
Extra: The format string with 2 params -- arg1 and arg2
The format string with 2 params -- %s and %sarg1
Extra: The format string with 3 params -- arg1 and arg2 and arg3
------------------------------------------------------------------------
I guess my questions are:
1) It appears that g++ considers the va_list type to be a (non-const)
char*. Is this normal? Is it standards compliant? (I didn't see
anything in the standard that would require it, but I am not a
language lawyer...)
2) It seems that the compiler is treating string literals differently
from variables which have been defined to be of type "const char*" --
i.e. in the two invocations of fun1 with the format2 string. In
particular, it seems to be doing an implicit conversion from string
constant to char*, but not from declared "const char*" to char*. But
I was under the impression that a string literal is in fact a "const
char*". Is there something in the standard that allows them to be
treated differently in this context?
3) Assuming that g++ is being standards compliant, is can anyone suggest
a better (portable, standards compliant) way to ensure that
fun1(format2, "arg1", "arg2")
ends up calling the
void fun1(const char* format, ...)
version of fun1?
Thanks!
Dan