Template argument deduction question

Hello, the program_options library fails one tests on EDG compilers (Intel, Como), which a failure to deduce template arguments for a certain call. After reading the standard for some time, I failed to understand the reason. Below is the test program: char* cmdline3_[1] = {}; template<class charT> void func(const charT* const argv[]) {} int main() { // P is 'const charT* const argv[]'cmdline3_ // A is 'char* cmdline3_[]' // // According to 14.8.2.1/2 // If P is not reference type // -If A is an array type, the pointer type produced // by the array-to-pointer standard convertion (4.2) // is used in place of A for type deduction. // // So, A should become 'char**' // The following does not compile. func(cmdline3_); char** p = cmdline3_; // This does compile, even though the argument type used for // type deduction should be the same as in example above. func(p); } Anybody can explain what's going on? TIA, Volodya

Vladimir Prus <ghost@cs.msu.su> writes:
Hello, the program_options library fails one tests on EDG compilers (Intel, Como), which a failure to deduce template arguments for a certain call. After reading the standard for some time, I failed to understand the reason.
Below is the test program:
char* cmdline3_[1] = {};
template<class charT> void func(const charT* const argv[]) {}
int main() { // P is 'const charT* const argv[]'cmdline3_ // A is 'char* cmdline3_[]'
I think A is 'char*[1]'
// According to 14.8.2.1/2 // If P is not reference type // -If A is an array type, the pointer type produced // by the array-to-pointer standard convertion (4.2) // is used in place of A for type deduction. // // So, A should become 'char**'
// The following does not compile. func(cmdline3_);
char** p = cmdline3_; // This does compile, even though the argument type used for // type deduction should be the same as in example above. func(p);
}
Anybody can explain what's going on?
It's well known that converting a char** into a char const** is a type-safety hole, so the language doesn't allow it (see D&E for the details, I think). 'char*[1]' converts (by array-to-pointer) to 'char**', but a 'const charT* const[]' parameter is equivalent to char const* const*', so a similar logic applies. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Below is the test program:
char* cmdline3_[1] = {};
template<class charT> void func(const charT* const argv[]) {}
int main() { // P is 'const charT* const argv[]'cmdline3_ // A is 'char* cmdline3_[]'
I think A is 'char*[1]'
Yes, but it still should be converted to char** for template argument deduction.
// According to 14.8.2.1/2 // If P is not reference type // -If A is an array type, the pointer type produced // by the array-to-pointer standard convertion (4.2) // is used in place of A for type deduction. // // So, A should become 'char**'
// The following does not compile. func(cmdline3_);
char** p = cmdline3_; // This does compile, even though the argument type used for // type deduction should be the same as in example above. func(p);
}
Anybody can explain what's going on?
It's well known that converting a char** into a char const** is a type-safety hole, so the language doesn't allow it (see D&E for the details, I think).
I know that. What's why the function argument is not (const charT* argv[]) but (const charT* const argv[])
'char*[1]' converts (by array-to-pointer) to 'char**', but a 'const charT* const[]' parameter is equivalent to char const* const*', so a similar logic applies.
I don't think so. In the second call, passing "char**" to the same function works without any problems. It looks like in the first call, compiler "forgets" to promote array to pointer. - Volodya

Vladimir Prus <ghost@cs.msu.su> writes:
David Abrahams wrote:
Below is the test program:
char* cmdline3_[1] = {};
template<class charT> void func(const charT* const argv[]) {}
int main() { // P is 'const charT* const argv[]'cmdline3_ // A is 'char* cmdline3_[]'
I think A is 'char*[1]'
Yes, but it still should be converted to char** for template argument deduction.
// According to 14.8.2.1/2 // If P is not reference type // -If A is an array type, the pointer type produced // by the array-to-pointer standard convertion (4.2) // is used in place of A for type deduction. // // So, A should become 'char**'
// The following does not compile. func(cmdline3_);
char** p = cmdline3_; // This does compile, even though the argument type used for // type deduction should be the same as in example above. func(p);
}
Anybody can explain what's going on?
It's well known that converting a char** into a char const** is a type-safety hole, so the language doesn't allow it (see D&E for the details, I think).
I know that. What's why the function argument is not (const charT* argv[]) but (const charT* const argv[])
'char*[1]' converts (by array-to-pointer) to 'char**', but a 'const charT* const[]' parameter is equivalent to char const* const*', so a similar logic applies.
I don't think so. In the second call, passing "char**" to the same function works without any problems. It looks like in the first call, compiler "forgets" to promote array to pointer.
On second thought, I think you've found an EDG bug. -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Fri, Jun 03, 2005 at 07:38:13AM -0400, David Abrahams wrote:
Vladimir Prus <ghost@cs.msu.su> writes:
Hello, the program_options library fails one tests on EDG compilers (Intel, Como), which a failure to deduce template arguments for a certain call. After reading the standard for some time, I failed to understand the reason.
Below is the test program:
char* cmdline3_[1] = {};
template<class charT> void func(const charT* const argv[]) {}
int main() { // P is 'const charT* const argv[]'cmdline3_ // A is 'char* cmdline3_[]'
I think A is 'char*[1]'
// According to 14.8.2.1/2 // If P is not reference type // -If A is an array type, the pointer type produced // by the array-to-pointer standard convertion (4.2) // is used in place of A for type deduction. // // So, A should become 'char**'
// The following does not compile. func(cmdline3_);
char** p = cmdline3_; // This does compile, even though the argument type used for // type deduction should be the same as in example above. func(p);
}
Anybody can explain what's going on?
It's well known that converting a char** into a char const** is a type-safety hole, so the language doesn't allow it (see D&E for the details, I think).
Or the example in [conv.qual] in the standard: int main() { const char c = 'c'; char* pc; const char** pcc = &pc; //1: not allowed *pcc = &c; *pc = 'C'; //2: modifies a const object }
'char*[1]' converts (by array-to-pointer) to 'char**', but a 'const charT* const[]' parameter is equivalent to char const* const*', so a similar logic applies.
That was what I thought the problem was, but why does the second call succeed? jon
participants (3)
-
David Abrahams
-
Jonathan Wakely
-
Vladimir Prus