Ambiguous C ++ templates?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
6
down vote

favorite












I need some help in this code. I declare two templates, the first converts the argument x from type T to type U and the second from type U to type T. If I call cast with 10, the compiler does not throw the exception, I think both meet the requirements to be used and There should be ambiguity, is that true? This code prints 10.



#include <iostream>

template<typename T,typename U>
U cast(T x)
return static_cast<U>(x);


template<typename T,typename U>
T cast(U x)
return static_cast<T>(x);


int main(int argc, char const *argv)

std::cout << cast<int,float>(10) << "n";
return 0;










share|improve this question







New contributor




wic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.



















  • If you change your code to cast<int,float>(10.0f) the second overload would be called. And if you changed it to cast<int,float>(10.0) the call would be ambiguous.
    – Praetorian
    15 mins ago














up vote
6
down vote

favorite












I need some help in this code. I declare two templates, the first converts the argument x from type T to type U and the second from type U to type T. If I call cast with 10, the compiler does not throw the exception, I think both meet the requirements to be used and There should be ambiguity, is that true? This code prints 10.



#include <iostream>

template<typename T,typename U>
U cast(T x)
return static_cast<U>(x);


template<typename T,typename U>
T cast(U x)
return static_cast<T>(x);


int main(int argc, char const *argv)

std::cout << cast<int,float>(10) << "n";
return 0;










share|improve this question







New contributor




wic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.



















  • If you change your code to cast<int,float>(10.0f) the second overload would be called. And if you changed it to cast<int,float>(10.0) the call would be ambiguous.
    – Praetorian
    15 mins ago












up vote
6
down vote

favorite









up vote
6
down vote

favorite











I need some help in this code. I declare two templates, the first converts the argument x from type T to type U and the second from type U to type T. If I call cast with 10, the compiler does not throw the exception, I think both meet the requirements to be used and There should be ambiguity, is that true? This code prints 10.



#include <iostream>

template<typename T,typename U>
U cast(T x)
return static_cast<U>(x);


template<typename T,typename U>
T cast(U x)
return static_cast<T>(x);


int main(int argc, char const *argv)

std::cout << cast<int,float>(10) << "n";
return 0;










share|improve this question







New contributor




wic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I need some help in this code. I declare two templates, the first converts the argument x from type T to type U and the second from type U to type T. If I call cast with 10, the compiler does not throw the exception, I think both meet the requirements to be used and There should be ambiguity, is that true? This code prints 10.



#include <iostream>

template<typename T,typename U>
U cast(T x)
return static_cast<U>(x);


template<typename T,typename U>
T cast(U x)
return static_cast<T>(x);


int main(int argc, char const *argv)

std::cout << cast<int,float>(10) << "n";
return 0;







c++ templates






share|improve this question







New contributor




wic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question







New contributor




wic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question






New contributor




wic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 22 mins ago









wic

785




785




New contributor




wic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





wic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






wic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











  • If you change your code to cast<int,float>(10.0f) the second overload would be called. And if you changed it to cast<int,float>(10.0) the call would be ambiguous.
    – Praetorian
    15 mins ago
















  • If you change your code to cast<int,float>(10.0f) the second overload would be called. And if you changed it to cast<int,float>(10.0) the call would be ambiguous.
    – Praetorian
    15 mins ago















If you change your code to cast<int,float>(10.0f) the second overload would be called. And if you changed it to cast<int,float>(10.0) the call would be ambiguous.
– Praetorian
15 mins ago




If you change your code to cast<int,float>(10.0f) the second overload would be called. And if you changed it to cast<int,float>(10.0) the call would be ambiguous.
– Praetorian
15 mins ago












2 Answers
2






active

oldest

votes

















up vote
12
down vote



accepted










When you use cast<int, float>, both templates are considered.



template<typename T=int,typename U=float>
U cast(T x);
template<typename T=int,typename U=float>
T cast(U x);


we then substitute:



template<typename T=int,typename U=float>
float cast(int x);
template<typename T=int,typename U=float>
int cast(float x);


at this point, there are no types to deduce. So we go to overload resolution.



In one case, we can take an int and convert to float when calling cast, and in the other we take a int and convert to int when calling cast. Note I'm not looking at all into the body of cast; the body is not relevant to overload resolution.



The second non-conversion (at the point of call) is a better match, so that overload is chosen.



If you did this:



std::cout << cast<int>(10) << "n";


things get more interesting:



template<typename T=int,typename U=?>
U cast(T x);
template<typename T=int,typename U=?>
T cast(U x);


for the first one, we cannot deduce U. For the second one we can.



template<typename T=int,typename U=?>
U cast(int x);
template<typename T=int,typename U=int>
int cast(int x);


so here we have one viable overload, and it is used.






share|improve this answer






















  • what OP's code actually does is convert from int to float (verified in assembler), so what non-conversion?
    – jakub_d
    10 mins ago










  • @jakub_d In the overload resolution of the argument. The body of a function does not change which function is called.
    – Yakk - Adam Nevraumont
    8 mins ago


















up vote
2
down vote













The instantiation is not ambiguous because the function argument exactly matches the first template parameter: the literal 10 is an int, which is also explicitly specified for the first template type.



You can make the instantiation ambiguous when the argument type does not match the explicitly specified types (thus, a conversion is necessary), e.g.



// error: call of overloaded 'cast<int, float>(unsigned int)' is ambiguous
std::cout << cast<int,float>(10u) << "n";





share|improve this answer




















    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: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );






    wic is a new contributor. Be nice, and check out our Code of Conduct.









     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52609797%2fambiguous-c-templates%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    12
    down vote



    accepted










    When you use cast<int, float>, both templates are considered.



    template<typename T=int,typename U=float>
    U cast(T x);
    template<typename T=int,typename U=float>
    T cast(U x);


    we then substitute:



    template<typename T=int,typename U=float>
    float cast(int x);
    template<typename T=int,typename U=float>
    int cast(float x);


    at this point, there are no types to deduce. So we go to overload resolution.



    In one case, we can take an int and convert to float when calling cast, and in the other we take a int and convert to int when calling cast. Note I'm not looking at all into the body of cast; the body is not relevant to overload resolution.



    The second non-conversion (at the point of call) is a better match, so that overload is chosen.



    If you did this:



    std::cout << cast<int>(10) << "n";


    things get more interesting:



    template<typename T=int,typename U=?>
    U cast(T x);
    template<typename T=int,typename U=?>
    T cast(U x);


    for the first one, we cannot deduce U. For the second one we can.



    template<typename T=int,typename U=?>
    U cast(int x);
    template<typename T=int,typename U=int>
    int cast(int x);


    so here we have one viable overload, and it is used.






    share|improve this answer






















    • what OP's code actually does is convert from int to float (verified in assembler), so what non-conversion?
      – jakub_d
      10 mins ago










    • @jakub_d In the overload resolution of the argument. The body of a function does not change which function is called.
      – Yakk - Adam Nevraumont
      8 mins ago















    up vote
    12
    down vote



    accepted










    When you use cast<int, float>, both templates are considered.



    template<typename T=int,typename U=float>
    U cast(T x);
    template<typename T=int,typename U=float>
    T cast(U x);


    we then substitute:



    template<typename T=int,typename U=float>
    float cast(int x);
    template<typename T=int,typename U=float>
    int cast(float x);


    at this point, there are no types to deduce. So we go to overload resolution.



    In one case, we can take an int and convert to float when calling cast, and in the other we take a int and convert to int when calling cast. Note I'm not looking at all into the body of cast; the body is not relevant to overload resolution.



    The second non-conversion (at the point of call) is a better match, so that overload is chosen.



    If you did this:



    std::cout << cast<int>(10) << "n";


    things get more interesting:



    template<typename T=int,typename U=?>
    U cast(T x);
    template<typename T=int,typename U=?>
    T cast(U x);


    for the first one, we cannot deduce U. For the second one we can.



    template<typename T=int,typename U=?>
    U cast(int x);
    template<typename T=int,typename U=int>
    int cast(int x);


    so here we have one viable overload, and it is used.






    share|improve this answer






















    • what OP's code actually does is convert from int to float (verified in assembler), so what non-conversion?
      – jakub_d
      10 mins ago










    • @jakub_d In the overload resolution of the argument. The body of a function does not change which function is called.
      – Yakk - Adam Nevraumont
      8 mins ago













    up vote
    12
    down vote



    accepted







    up vote
    12
    down vote



    accepted






    When you use cast<int, float>, both templates are considered.



    template<typename T=int,typename U=float>
    U cast(T x);
    template<typename T=int,typename U=float>
    T cast(U x);


    we then substitute:



    template<typename T=int,typename U=float>
    float cast(int x);
    template<typename T=int,typename U=float>
    int cast(float x);


    at this point, there are no types to deduce. So we go to overload resolution.



    In one case, we can take an int and convert to float when calling cast, and in the other we take a int and convert to int when calling cast. Note I'm not looking at all into the body of cast; the body is not relevant to overload resolution.



    The second non-conversion (at the point of call) is a better match, so that overload is chosen.



    If you did this:



    std::cout << cast<int>(10) << "n";


    things get more interesting:



    template<typename T=int,typename U=?>
    U cast(T x);
    template<typename T=int,typename U=?>
    T cast(U x);


    for the first one, we cannot deduce U. For the second one we can.



    template<typename T=int,typename U=?>
    U cast(int x);
    template<typename T=int,typename U=int>
    int cast(int x);


    so here we have one viable overload, and it is used.






    share|improve this answer














    When you use cast<int, float>, both templates are considered.



    template<typename T=int,typename U=float>
    U cast(T x);
    template<typename T=int,typename U=float>
    T cast(U x);


    we then substitute:



    template<typename T=int,typename U=float>
    float cast(int x);
    template<typename T=int,typename U=float>
    int cast(float x);


    at this point, there are no types to deduce. So we go to overload resolution.



    In one case, we can take an int and convert to float when calling cast, and in the other we take a int and convert to int when calling cast. Note I'm not looking at all into the body of cast; the body is not relevant to overload resolution.



    The second non-conversion (at the point of call) is a better match, so that overload is chosen.



    If you did this:



    std::cout << cast<int>(10) << "n";


    things get more interesting:



    template<typename T=int,typename U=?>
    U cast(T x);
    template<typename T=int,typename U=?>
    T cast(U x);


    for the first one, we cannot deduce U. For the second one we can.



    template<typename T=int,typename U=?>
    U cast(int x);
    template<typename T=int,typename U=int>
    int cast(int x);


    so here we have one viable overload, and it is used.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 7 mins ago

























    answered 18 mins ago









    Yakk - Adam Nevraumont

    172k18175354




    172k18175354











    • what OP's code actually does is convert from int to float (verified in assembler), so what non-conversion?
      – jakub_d
      10 mins ago










    • @jakub_d In the overload resolution of the argument. The body of a function does not change which function is called.
      – Yakk - Adam Nevraumont
      8 mins ago

















    • what OP's code actually does is convert from int to float (verified in assembler), so what non-conversion?
      – jakub_d
      10 mins ago










    • @jakub_d In the overload resolution of the argument. The body of a function does not change which function is called.
      – Yakk - Adam Nevraumont
      8 mins ago
















    what OP's code actually does is convert from int to float (verified in assembler), so what non-conversion?
    – jakub_d
    10 mins ago




    what OP's code actually does is convert from int to float (verified in assembler), so what non-conversion?
    – jakub_d
    10 mins ago












    @jakub_d In the overload resolution of the argument. The body of a function does not change which function is called.
    – Yakk - Adam Nevraumont
    8 mins ago





    @jakub_d In the overload resolution of the argument. The body of a function does not change which function is called.
    – Yakk - Adam Nevraumont
    8 mins ago













    up vote
    2
    down vote













    The instantiation is not ambiguous because the function argument exactly matches the first template parameter: the literal 10 is an int, which is also explicitly specified for the first template type.



    You can make the instantiation ambiguous when the argument type does not match the explicitly specified types (thus, a conversion is necessary), e.g.



    // error: call of overloaded 'cast<int, float>(unsigned int)' is ambiguous
    std::cout << cast<int,float>(10u) << "n";





    share|improve this answer
























      up vote
      2
      down vote













      The instantiation is not ambiguous because the function argument exactly matches the first template parameter: the literal 10 is an int, which is also explicitly specified for the first template type.



      You can make the instantiation ambiguous when the argument type does not match the explicitly specified types (thus, a conversion is necessary), e.g.



      // error: call of overloaded 'cast<int, float>(unsigned int)' is ambiguous
      std::cout << cast<int,float>(10u) << "n";





      share|improve this answer






















        up vote
        2
        down vote










        up vote
        2
        down vote









        The instantiation is not ambiguous because the function argument exactly matches the first template parameter: the literal 10 is an int, which is also explicitly specified for the first template type.



        You can make the instantiation ambiguous when the argument type does not match the explicitly specified types (thus, a conversion is necessary), e.g.



        // error: call of overloaded 'cast<int, float>(unsigned int)' is ambiguous
        std::cout << cast<int,float>(10u) << "n";





        share|improve this answer












        The instantiation is not ambiguous because the function argument exactly matches the first template parameter: the literal 10 is an int, which is also explicitly specified for the first template type.



        You can make the instantiation ambiguous when the argument type does not match the explicitly specified types (thus, a conversion is necessary), e.g.



        // error: call of overloaded 'cast<int, float>(unsigned int)' is ambiguous
        std::cout << cast<int,float>(10u) << "n";






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 19 mins ago









        lubgr

        7,62521442




        7,62521442




















            wic is a new contributor. Be nice, and check out our Code of Conduct.









             

            draft saved


            draft discarded


















            wic is a new contributor. Be nice, and check out our Code of Conduct.












            wic is a new contributor. Be nice, and check out our Code of Conduct.











            wic is a new contributor. Be nice, and check out our Code of Conduct.













             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52609797%2fambiguous-c-templates%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            What does second last employer means? [closed]

            List of Gilmore Girls characters

            Confectionery