Program fails to call the specialized template implementation
up vote
0
down vote
favorite
I am trying to learn C++ template. While I run the following example, the program couldn't call the specialized template implementation. Therefore, I got the wrong output. Could anybody tell why?
template <class T>
T max(T a, T b)
cout << "2 ..." <<endl;
return a > b ? a : b;
template<>
char* max(char* a, char* b)
cout << "1 ..." <<endl;
return strcmp(a, b) > 0 ? a : b;
int main()
cout << max("Aladdin", "Jasmine") << endl;
return 0;
c++ templates
add a comment |
up vote
0
down vote
favorite
I am trying to learn C++ template. While I run the following example, the program couldn't call the specialized template implementation. Therefore, I got the wrong output. Could anybody tell why?
template <class T>
T max(T a, T b)
cout << "2 ..." <<endl;
return a > b ? a : b;
template<>
char* max(char* a, char* b)
cout << "1 ..." <<endl;
return strcmp(a, b) > 0 ? a : b;
int main()
cout << max("Aladdin", "Jasmine") << endl;
return 0;
c++ templates
Tryconst char* max(const char* a, const char* b)for the specialization.
– πάντα ῥεῖ
Nov 11 at 0:04
Yes, this solves the problem. But why? What are other cases I need to add const key word for template specialization?
– Spring19981
Nov 11 at 0:16
You probably should useconstin general, if you don't plan to apply changes to the parameters.
– πάντα ῥεῖ
Nov 11 at 0:21
Because a string literal is an array ofconst char, and passing it as a non-constpointer will (after conversions) treat it as non-const. The template function is therefore a better match.
– Peter
Nov 11 at 0:36
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I am trying to learn C++ template. While I run the following example, the program couldn't call the specialized template implementation. Therefore, I got the wrong output. Could anybody tell why?
template <class T>
T max(T a, T b)
cout << "2 ..." <<endl;
return a > b ? a : b;
template<>
char* max(char* a, char* b)
cout << "1 ..." <<endl;
return strcmp(a, b) > 0 ? a : b;
int main()
cout << max("Aladdin", "Jasmine") << endl;
return 0;
c++ templates
I am trying to learn C++ template. While I run the following example, the program couldn't call the specialized template implementation. Therefore, I got the wrong output. Could anybody tell why?
template <class T>
T max(T a, T b)
cout << "2 ..." <<endl;
return a > b ? a : b;
template<>
char* max(char* a, char* b)
cout << "1 ..." <<endl;
return strcmp(a, b) > 0 ? a : b;
int main()
cout << max("Aladdin", "Jasmine") << endl;
return 0;
c++ templates
c++ templates
edited Nov 11 at 0:04
πάντα ῥεῖ
71.3k970133
71.3k970133
asked Nov 11 at 0:02
Spring19981
73
73
Tryconst char* max(const char* a, const char* b)for the specialization.
– πάντα ῥεῖ
Nov 11 at 0:04
Yes, this solves the problem. But why? What are other cases I need to add const key word for template specialization?
– Spring19981
Nov 11 at 0:16
You probably should useconstin general, if you don't plan to apply changes to the parameters.
– πάντα ῥεῖ
Nov 11 at 0:21
Because a string literal is an array ofconst char, and passing it as a non-constpointer will (after conversions) treat it as non-const. The template function is therefore a better match.
– Peter
Nov 11 at 0:36
add a comment |
Tryconst char* max(const char* a, const char* b)for the specialization.
– πάντα ῥεῖ
Nov 11 at 0:04
Yes, this solves the problem. But why? What are other cases I need to add const key word for template specialization?
– Spring19981
Nov 11 at 0:16
You probably should useconstin general, if you don't plan to apply changes to the parameters.
– πάντα ῥεῖ
Nov 11 at 0:21
Because a string literal is an array ofconst char, and passing it as a non-constpointer will (after conversions) treat it as non-const. The template function is therefore a better match.
– Peter
Nov 11 at 0:36
Try
const char* max(const char* a, const char* b) for the specialization.– πάντα ῥεῖ
Nov 11 at 0:04
Try
const char* max(const char* a, const char* b) for the specialization.– πάντα ῥεῖ
Nov 11 at 0:04
Yes, this solves the problem. But why? What are other cases I need to add const key word for template specialization?
– Spring19981
Nov 11 at 0:16
Yes, this solves the problem. But why? What are other cases I need to add const key word for template specialization?
– Spring19981
Nov 11 at 0:16
You probably should use
const in general, if you don't plan to apply changes to the parameters.– πάντα ῥεῖ
Nov 11 at 0:21
You probably should use
const in general, if you don't plan to apply changes to the parameters.– πάντα ῥεῖ
Nov 11 at 0:21
Because a string literal is an array of
const char, and passing it as a non-const pointer will (after conversions) treat it as non-const. The template function is therefore a better match.– Peter
Nov 11 at 0:36
Because a string literal is an array of
const char, and passing it as a non-const pointer will (after conversions) treat it as non-const. The template function is therefore a better match.– Peter
Nov 11 at 0:36
add a comment |
2 Answers
2
active
oldest
votes
up vote
2
down vote
The arguments are passed as constant char. Therefore, try the following code instead. Note that I also included the necessary header file includes. Moreover, it is highly advisable to use std::cout, or use using std::cout;.
#include <iostream>
#include <cstring>
template <class T>
T max(T a, T b)
std::cout << "2 ..." << std::endl;
return a > b ? a : b;
template<>
const char* max(const char* a, const char* b)
std::cout << "1 ..." << std::endl;
return std::strcmp(a, b) > 0 ? a : b;
int main()
std::cout << max("Aladdin", "Jasmine") << std::endl;
return 0;
add a comment |
up vote
0
down vote
The reason you're seeing the issue is that the arguments you're passing are of type char const * (also can be spelled const char *). There isn't any standard way that I know of in C++ to print out the full name of a type. But there is a way to test this sort of thing..
One of the problems of templates is that the system will expand any templates it can. And so you will have code mysteriously work a certain way and not be completely sure why. One way you could've gotten the compiler to tell you exactly what the problem was in this case was to try to remove the template:
#include <iostream>
#include <cstring>
using ::std::cout;
using ::std::strcmp;
char* max(char* a, char* b)
cout << "1 ..." << 'n'; // Don't use ::std::endl Use cerr if you need flushing.
return strcmp(a, b) > 0 ? a : b;
int main()
cout << max("Aladdin", "Jasmine") << 'n';
return 0;
The compiler would've helpfully told you that you were trying to call a function that took non-const arguments with const arguments, and you would've learned exactly what the problem was.
The answers to an earlier question on this topic seem to suggest that this kind of specialization can't be done. Basically, the claim was that string literals are really of typeconst char[N], and so you were unable to specialize without hardcoding a specific value ofNinto the template. That thread was from 2011, so did something change in the more recent cpp standards to make this "just work"? Do you happen to know?
– tel
Nov 11 at 1:05
Also, what's wrong withstd::endl? Is'n'considered portable now?
– tel
Nov 11 at 1:06
2
@tel I believe the case you link to is substantially different because the argument is passed by reference. However in this question the argument is passed by value, so the array-to-pointer conversion is applied as part of template argument deduction.
– M.M
Nov 11 at 1:15
<< std::endlis equivalent to<< 'n' << std::flushand the flush is redundant in most cases
– M.M
Nov 11 at 1:16
1
@tel -'n'has always been portable.
– Omnifarious
Nov 11 at 1:18
|
show 2 more comments
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
The arguments are passed as constant char. Therefore, try the following code instead. Note that I also included the necessary header file includes. Moreover, it is highly advisable to use std::cout, or use using std::cout;.
#include <iostream>
#include <cstring>
template <class T>
T max(T a, T b)
std::cout << "2 ..." << std::endl;
return a > b ? a : b;
template<>
const char* max(const char* a, const char* b)
std::cout << "1 ..." << std::endl;
return std::strcmp(a, b) > 0 ? a : b;
int main()
std::cout << max("Aladdin", "Jasmine") << std::endl;
return 0;
add a comment |
up vote
2
down vote
The arguments are passed as constant char. Therefore, try the following code instead. Note that I also included the necessary header file includes. Moreover, it is highly advisable to use std::cout, or use using std::cout;.
#include <iostream>
#include <cstring>
template <class T>
T max(T a, T b)
std::cout << "2 ..." << std::endl;
return a > b ? a : b;
template<>
const char* max(const char* a, const char* b)
std::cout << "1 ..." << std::endl;
return std::strcmp(a, b) > 0 ? a : b;
int main()
std::cout << max("Aladdin", "Jasmine") << std::endl;
return 0;
add a comment |
up vote
2
down vote
up vote
2
down vote
The arguments are passed as constant char. Therefore, try the following code instead. Note that I also included the necessary header file includes. Moreover, it is highly advisable to use std::cout, or use using std::cout;.
#include <iostream>
#include <cstring>
template <class T>
T max(T a, T b)
std::cout << "2 ..." << std::endl;
return a > b ? a : b;
template<>
const char* max(const char* a, const char* b)
std::cout << "1 ..." << std::endl;
return std::strcmp(a, b) > 0 ? a : b;
int main()
std::cout << max("Aladdin", "Jasmine") << std::endl;
return 0;
The arguments are passed as constant char. Therefore, try the following code instead. Note that I also included the necessary header file includes. Moreover, it is highly advisable to use std::cout, or use using std::cout;.
#include <iostream>
#include <cstring>
template <class T>
T max(T a, T b)
std::cout << "2 ..." << std::endl;
return a > b ? a : b;
template<>
const char* max(const char* a, const char* b)
std::cout << "1 ..." << std::endl;
return std::strcmp(a, b) > 0 ? a : b;
int main()
std::cout << max("Aladdin", "Jasmine") << std::endl;
return 0;
edited Nov 11 at 0:17
πάντα ῥεῖ
71.3k970133
71.3k970133
answered Nov 11 at 0:12
DVB
314
314
add a comment |
add a comment |
up vote
0
down vote
The reason you're seeing the issue is that the arguments you're passing are of type char const * (also can be spelled const char *). There isn't any standard way that I know of in C++ to print out the full name of a type. But there is a way to test this sort of thing..
One of the problems of templates is that the system will expand any templates it can. And so you will have code mysteriously work a certain way and not be completely sure why. One way you could've gotten the compiler to tell you exactly what the problem was in this case was to try to remove the template:
#include <iostream>
#include <cstring>
using ::std::cout;
using ::std::strcmp;
char* max(char* a, char* b)
cout << "1 ..." << 'n'; // Don't use ::std::endl Use cerr if you need flushing.
return strcmp(a, b) > 0 ? a : b;
int main()
cout << max("Aladdin", "Jasmine") << 'n';
return 0;
The compiler would've helpfully told you that you were trying to call a function that took non-const arguments with const arguments, and you would've learned exactly what the problem was.
The answers to an earlier question on this topic seem to suggest that this kind of specialization can't be done. Basically, the claim was that string literals are really of typeconst char[N], and so you were unable to specialize without hardcoding a specific value ofNinto the template. That thread was from 2011, so did something change in the more recent cpp standards to make this "just work"? Do you happen to know?
– tel
Nov 11 at 1:05
Also, what's wrong withstd::endl? Is'n'considered portable now?
– tel
Nov 11 at 1:06
2
@tel I believe the case you link to is substantially different because the argument is passed by reference. However in this question the argument is passed by value, so the array-to-pointer conversion is applied as part of template argument deduction.
– M.M
Nov 11 at 1:15
<< std::endlis equivalent to<< 'n' << std::flushand the flush is redundant in most cases
– M.M
Nov 11 at 1:16
1
@tel -'n'has always been portable.
– Omnifarious
Nov 11 at 1:18
|
show 2 more comments
up vote
0
down vote
The reason you're seeing the issue is that the arguments you're passing are of type char const * (also can be spelled const char *). There isn't any standard way that I know of in C++ to print out the full name of a type. But there is a way to test this sort of thing..
One of the problems of templates is that the system will expand any templates it can. And so you will have code mysteriously work a certain way and not be completely sure why. One way you could've gotten the compiler to tell you exactly what the problem was in this case was to try to remove the template:
#include <iostream>
#include <cstring>
using ::std::cout;
using ::std::strcmp;
char* max(char* a, char* b)
cout << "1 ..." << 'n'; // Don't use ::std::endl Use cerr if you need flushing.
return strcmp(a, b) > 0 ? a : b;
int main()
cout << max("Aladdin", "Jasmine") << 'n';
return 0;
The compiler would've helpfully told you that you were trying to call a function that took non-const arguments with const arguments, and you would've learned exactly what the problem was.
The answers to an earlier question on this topic seem to suggest that this kind of specialization can't be done. Basically, the claim was that string literals are really of typeconst char[N], and so you were unable to specialize without hardcoding a specific value ofNinto the template. That thread was from 2011, so did something change in the more recent cpp standards to make this "just work"? Do you happen to know?
– tel
Nov 11 at 1:05
Also, what's wrong withstd::endl? Is'n'considered portable now?
– tel
Nov 11 at 1:06
2
@tel I believe the case you link to is substantially different because the argument is passed by reference. However in this question the argument is passed by value, so the array-to-pointer conversion is applied as part of template argument deduction.
– M.M
Nov 11 at 1:15
<< std::endlis equivalent to<< 'n' << std::flushand the flush is redundant in most cases
– M.M
Nov 11 at 1:16
1
@tel -'n'has always been portable.
– Omnifarious
Nov 11 at 1:18
|
show 2 more comments
up vote
0
down vote
up vote
0
down vote
The reason you're seeing the issue is that the arguments you're passing are of type char const * (also can be spelled const char *). There isn't any standard way that I know of in C++ to print out the full name of a type. But there is a way to test this sort of thing..
One of the problems of templates is that the system will expand any templates it can. And so you will have code mysteriously work a certain way and not be completely sure why. One way you could've gotten the compiler to tell you exactly what the problem was in this case was to try to remove the template:
#include <iostream>
#include <cstring>
using ::std::cout;
using ::std::strcmp;
char* max(char* a, char* b)
cout << "1 ..." << 'n'; // Don't use ::std::endl Use cerr if you need flushing.
return strcmp(a, b) > 0 ? a : b;
int main()
cout << max("Aladdin", "Jasmine") << 'n';
return 0;
The compiler would've helpfully told you that you were trying to call a function that took non-const arguments with const arguments, and you would've learned exactly what the problem was.
The reason you're seeing the issue is that the arguments you're passing are of type char const * (also can be spelled const char *). There isn't any standard way that I know of in C++ to print out the full name of a type. But there is a way to test this sort of thing..
One of the problems of templates is that the system will expand any templates it can. And so you will have code mysteriously work a certain way and not be completely sure why. One way you could've gotten the compiler to tell you exactly what the problem was in this case was to try to remove the template:
#include <iostream>
#include <cstring>
using ::std::cout;
using ::std::strcmp;
char* max(char* a, char* b)
cout << "1 ..." << 'n'; // Don't use ::std::endl Use cerr if you need flushing.
return strcmp(a, b) > 0 ? a : b;
int main()
cout << max("Aladdin", "Jasmine") << 'n';
return 0;
The compiler would've helpfully told you that you were trying to call a function that took non-const arguments with const arguments, and you would've learned exactly what the problem was.
edited Nov 11 at 0:47
answered Nov 11 at 0:34
Omnifarious
39.8k1196157
39.8k1196157
The answers to an earlier question on this topic seem to suggest that this kind of specialization can't be done. Basically, the claim was that string literals are really of typeconst char[N], and so you were unable to specialize without hardcoding a specific value ofNinto the template. That thread was from 2011, so did something change in the more recent cpp standards to make this "just work"? Do you happen to know?
– tel
Nov 11 at 1:05
Also, what's wrong withstd::endl? Is'n'considered portable now?
– tel
Nov 11 at 1:06
2
@tel I believe the case you link to is substantially different because the argument is passed by reference. However in this question the argument is passed by value, so the array-to-pointer conversion is applied as part of template argument deduction.
– M.M
Nov 11 at 1:15
<< std::endlis equivalent to<< 'n' << std::flushand the flush is redundant in most cases
– M.M
Nov 11 at 1:16
1
@tel -'n'has always been portable.
– Omnifarious
Nov 11 at 1:18
|
show 2 more comments
The answers to an earlier question on this topic seem to suggest that this kind of specialization can't be done. Basically, the claim was that string literals are really of typeconst char[N], and so you were unable to specialize without hardcoding a specific value ofNinto the template. That thread was from 2011, so did something change in the more recent cpp standards to make this "just work"? Do you happen to know?
– tel
Nov 11 at 1:05
Also, what's wrong withstd::endl? Is'n'considered portable now?
– tel
Nov 11 at 1:06
2
@tel I believe the case you link to is substantially different because the argument is passed by reference. However in this question the argument is passed by value, so the array-to-pointer conversion is applied as part of template argument deduction.
– M.M
Nov 11 at 1:15
<< std::endlis equivalent to<< 'n' << std::flushand the flush is redundant in most cases
– M.M
Nov 11 at 1:16
1
@tel -'n'has always been portable.
– Omnifarious
Nov 11 at 1:18
The answers to an earlier question on this topic seem to suggest that this kind of specialization can't be done. Basically, the claim was that string literals are really of type
const char[N], and so you were unable to specialize without hardcoding a specific value of N into the template. That thread was from 2011, so did something change in the more recent cpp standards to make this "just work"? Do you happen to know?– tel
Nov 11 at 1:05
The answers to an earlier question on this topic seem to suggest that this kind of specialization can't be done. Basically, the claim was that string literals are really of type
const char[N], and so you were unable to specialize without hardcoding a specific value of N into the template. That thread was from 2011, so did something change in the more recent cpp standards to make this "just work"? Do you happen to know?– tel
Nov 11 at 1:05
Also, what's wrong with
std::endl? Is 'n' considered portable now?– tel
Nov 11 at 1:06
Also, what's wrong with
std::endl? Is 'n' considered portable now?– tel
Nov 11 at 1:06
2
2
@tel I believe the case you link to is substantially different because the argument is passed by reference. However in this question the argument is passed by value, so the array-to-pointer conversion is applied as part of template argument deduction.
– M.M
Nov 11 at 1:15
@tel I believe the case you link to is substantially different because the argument is passed by reference. However in this question the argument is passed by value, so the array-to-pointer conversion is applied as part of template argument deduction.
– M.M
Nov 11 at 1:15
<< std::endl is equivalent to << 'n' << std::flush and the flush is redundant in most cases– M.M
Nov 11 at 1:16
<< std::endl is equivalent to << 'n' << std::flush and the flush is redundant in most cases– M.M
Nov 11 at 1:16
1
1
@tel -
'n' has always been portable.– Omnifarious
Nov 11 at 1:18
@tel -
'n' has always been portable.– Omnifarious
Nov 11 at 1:18
|
show 2 more comments
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244624%2fprogram-fails-to-call-the-specialized-template-implementation%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Try
const char* max(const char* a, const char* b)for the specialization.– πάντα ῥεῖ
Nov 11 at 0:04
Yes, this solves the problem. But why? What are other cases I need to add const key word for template specialization?
– Spring19981
Nov 11 at 0:16
You probably should use
constin general, if you don't plan to apply changes to the parameters.– πάντα ῥεῖ
Nov 11 at 0:21
Because a string literal is an array of
const char, and passing it as a non-constpointer will (after conversions) treat it as non-const. The template function is therefore a better match.– Peter
Nov 11 at 0:36