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;










share|improve this question























  • 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 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















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;










share|improve this question























  • 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 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













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;










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 11 at 0:04









πάντα ῥεῖ

71.3k970133




71.3k970133










asked Nov 11 at 0:02









Spring19981

73




73











  • 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 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

















  • 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 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
















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













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;






share|improve this answer





























    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.






    share|improve this answer






















    • 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






    • 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::endl is equivalent to << 'n' << std::flush and 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










    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    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

























    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;






    share|improve this answer


























      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;






      share|improve this answer
























        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;






        share|improve this answer














        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;







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 11 at 0:17









        πάντα ῥεῖ

        71.3k970133




        71.3k970133










        answered Nov 11 at 0:12









        DVB

        314




        314






















            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.






            share|improve this answer






















            • 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






            • 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::endl is equivalent to << 'n' << std::flush and 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














            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.






            share|improve this answer






















            • 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






            • 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::endl is equivalent to << 'n' << std::flush and 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












            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.






            share|improve this answer














            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.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            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 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






            • 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::endl is equivalent to << 'n' << std::flush and 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










            • Also, what's wrong with std::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::endl is equivalent to << 'n' << std::flush and 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

















             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            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





















































            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







            這個網誌中的熱門文章

            What does pagestruct do in Eviews?

            Dutch intervention in Lombok and Karangasem

            Channel Islands