Why does the implicit type conversion not work in template deduction?

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











up vote
10
down vote

favorite
1












In the following code, I want to call a template function by implicitly converting an int to a Scalar<int> object.



#include<iostream>
using namespace std;

template<typename Dtype>
class Scalar
public:
Scalar(Dtype v) : value_(v)
private:
Dtype value_;
;

template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;


int main()
int a = 1;
func(a, 2);
//int b = 2;
//func(a, b);
return 0;



Why does the template argument deduction/substitution fail? And the commented-codes are also wrong.



test.cpp: In function ‘int main()’:
test.cpp:19:12: error: no matching function for call to ‘func(int&, int)’
func(a, 2);
^
test.cpp:19:12: note: candidate is:
test.cpp:13:6: note: template<class Dtype> void func(int, Scalar<Dtype>)
void func(int a, Scalar<Dtype> b){
^
test.cpp:13:6: note: template argument deduction/substitution failed:
test.cpp:19:12: note: mismatched types ‘Scalar<Dtype>’ and ‘int’
func(a, 2);









share|improve this question



















  • 3




    Possible duplicate of C++ implicit type conversion with template
    – jwismar
    1 hour ago














up vote
10
down vote

favorite
1












In the following code, I want to call a template function by implicitly converting an int to a Scalar<int> object.



#include<iostream>
using namespace std;

template<typename Dtype>
class Scalar
public:
Scalar(Dtype v) : value_(v)
private:
Dtype value_;
;

template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;


int main()
int a = 1;
func(a, 2);
//int b = 2;
//func(a, b);
return 0;



Why does the template argument deduction/substitution fail? And the commented-codes are also wrong.



test.cpp: In function ‘int main()’:
test.cpp:19:12: error: no matching function for call to ‘func(int&, int)’
func(a, 2);
^
test.cpp:19:12: note: candidate is:
test.cpp:13:6: note: template<class Dtype> void func(int, Scalar<Dtype>)
void func(int a, Scalar<Dtype> b){
^
test.cpp:13:6: note: template argument deduction/substitution failed:
test.cpp:19:12: note: mismatched types ‘Scalar<Dtype>’ and ‘int’
func(a, 2);









share|improve this question



















  • 3




    Possible duplicate of C++ implicit type conversion with template
    – jwismar
    1 hour ago












up vote
10
down vote

favorite
1









up vote
10
down vote

favorite
1






1





In the following code, I want to call a template function by implicitly converting an int to a Scalar<int> object.



#include<iostream>
using namespace std;

template<typename Dtype>
class Scalar
public:
Scalar(Dtype v) : value_(v)
private:
Dtype value_;
;

template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;


int main()
int a = 1;
func(a, 2);
//int b = 2;
//func(a, b);
return 0;



Why does the template argument deduction/substitution fail? And the commented-codes are also wrong.



test.cpp: In function ‘int main()’:
test.cpp:19:12: error: no matching function for call to ‘func(int&, int)’
func(a, 2);
^
test.cpp:19:12: note: candidate is:
test.cpp:13:6: note: template<class Dtype> void func(int, Scalar<Dtype>)
void func(int a, Scalar<Dtype> b){
^
test.cpp:13:6: note: template argument deduction/substitution failed:
test.cpp:19:12: note: mismatched types ‘Scalar<Dtype>’ and ‘int’
func(a, 2);









share|improve this question















In the following code, I want to call a template function by implicitly converting an int to a Scalar<int> object.



#include<iostream>
using namespace std;

template<typename Dtype>
class Scalar
public:
Scalar(Dtype v) : value_(v)
private:
Dtype value_;
;

template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;


int main()
int a = 1;
func(a, 2);
//int b = 2;
//func(a, b);
return 0;



Why does the template argument deduction/substitution fail? And the commented-codes are also wrong.



test.cpp: In function ‘int main()’:
test.cpp:19:12: error: no matching function for call to ‘func(int&, int)’
func(a, 2);
^
test.cpp:19:12: note: candidate is:
test.cpp:13:6: note: template<class Dtype> void func(int, Scalar<Dtype>)
void func(int a, Scalar<Dtype> b){
^
test.cpp:13:6: note: template argument deduction/substitution failed:
test.cpp:19:12: note: mismatched types ‘Scalar<Dtype>’ and ‘int’
func(a, 2);






c++ c++11 templates






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 1 hour ago









YSC

18.5k34388




18.5k34388










asked 1 hour ago









Yulong Ao

441617




441617







  • 3




    Possible duplicate of C++ implicit type conversion with template
    – jwismar
    1 hour ago












  • 3




    Possible duplicate of C++ implicit type conversion with template
    – jwismar
    1 hour ago







3




3




Possible duplicate of C++ implicit type conversion with template
– jwismar
1 hour ago




Possible duplicate of C++ implicit type conversion with template
– jwismar
1 hour ago












2 Answers
2






active

oldest

votes

















up vote
10
down vote













Because template argument deduction is not that smart: it does not (by design) consider user-defined conversions. And int -> Scalar<int> is a user-defined conversion.



If you want to use TAD, you need to convert your argument at the caller site:



func(a, Scalar<int>2); 


or define a deduction guide1 for Scalar and call f:



func(a, Scalar2); // C++17 only


Alternatively, you can explicitly instantiate f:



func<int>(a, 2); 



1) The default deduction guide is sufficient: demo.






share|improve this answer






















  • I've tested all three of your solutions and they will work as is; however if the OP declared Scalar() as explicit the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
    – Francis Cugler
    1 hour ago







  • 1




    @FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
    – YSC
    1 hour ago

















up vote
1
down vote













template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;

template<typename Dtype>
void func(int a, Dtype b)
func(a, Scalar<Dtype>(std::move(b)));



template argument deduction is pattern matching, and it only matches the types or their base types exactly. It does no conversion.



Conversion is done later, at overload resolution & function call time.



Here, we add another overload that explicitly forwards to the one you want.






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: 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%2f53227713%2fwhy-does-the-implicit-type-conversion-not-work-in-template-deduction%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
    10
    down vote













    Because template argument deduction is not that smart: it does not (by design) consider user-defined conversions. And int -> Scalar<int> is a user-defined conversion.



    If you want to use TAD, you need to convert your argument at the caller site:



    func(a, Scalar<int>2); 


    or define a deduction guide1 for Scalar and call f:



    func(a, Scalar2); // C++17 only


    Alternatively, you can explicitly instantiate f:



    func<int>(a, 2); 



    1) The default deduction guide is sufficient: demo.






    share|improve this answer






















    • I've tested all three of your solutions and they will work as is; however if the OP declared Scalar() as explicit the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
      – Francis Cugler
      1 hour ago







    • 1




      @FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
      – YSC
      1 hour ago














    up vote
    10
    down vote













    Because template argument deduction is not that smart: it does not (by design) consider user-defined conversions. And int -> Scalar<int> is a user-defined conversion.



    If you want to use TAD, you need to convert your argument at the caller site:



    func(a, Scalar<int>2); 


    or define a deduction guide1 for Scalar and call f:



    func(a, Scalar2); // C++17 only


    Alternatively, you can explicitly instantiate f:



    func<int>(a, 2); 



    1) The default deduction guide is sufficient: demo.






    share|improve this answer






















    • I've tested all three of your solutions and they will work as is; however if the OP declared Scalar() as explicit the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
      – Francis Cugler
      1 hour ago







    • 1




      @FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
      – YSC
      1 hour ago












    up vote
    10
    down vote










    up vote
    10
    down vote









    Because template argument deduction is not that smart: it does not (by design) consider user-defined conversions. And int -> Scalar<int> is a user-defined conversion.



    If you want to use TAD, you need to convert your argument at the caller site:



    func(a, Scalar<int>2); 


    or define a deduction guide1 for Scalar and call f:



    func(a, Scalar2); // C++17 only


    Alternatively, you can explicitly instantiate f:



    func<int>(a, 2); 



    1) The default deduction guide is sufficient: demo.






    share|improve this answer














    Because template argument deduction is not that smart: it does not (by design) consider user-defined conversions. And int -> Scalar<int> is a user-defined conversion.



    If you want to use TAD, you need to convert your argument at the caller site:



    func(a, Scalar<int>2); 


    or define a deduction guide1 for Scalar and call f:



    func(a, Scalar2); // C++17 only


    Alternatively, you can explicitly instantiate f:



    func<int>(a, 2); 



    1) The default deduction guide is sufficient: demo.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 1 hour ago

























    answered 1 hour ago









    YSC

    18.5k34388




    18.5k34388











    • I've tested all three of your solutions and they will work as is; however if the OP declared Scalar() as explicit the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
      – Francis Cugler
      1 hour ago







    • 1




      @FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
      – YSC
      1 hour ago
















    • I've tested all three of your solutions and they will work as is; however if the OP declared Scalar() as explicit the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
      – Francis Cugler
      1 hour ago







    • 1




      @FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
      – YSC
      1 hour ago















    I've tested all three of your solutions and they will work as is; however if the OP declared Scalar() as explicit the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
    – Francis Cugler
    1 hour ago





    I've tested all three of your solutions and they will work as is; however if the OP declared Scalar() as explicit the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
    – Francis Cugler
    1 hour ago





    1




    1




    @FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
    – YSC
    1 hour ago




    @FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
    – YSC
    1 hour ago












    up vote
    1
    down vote













    template<typename Dtype>
    void func(int a, Scalar<Dtype> b)
    cout << "ok" <<endl;

    template<typename Dtype>
    void func(int a, Dtype b)
    func(a, Scalar<Dtype>(std::move(b)));



    template argument deduction is pattern matching, and it only matches the types or their base types exactly. It does no conversion.



    Conversion is done later, at overload resolution & function call time.



    Here, we add another overload that explicitly forwards to the one you want.






    share|improve this answer
























      up vote
      1
      down vote













      template<typename Dtype>
      void func(int a, Scalar<Dtype> b)
      cout << "ok" <<endl;

      template<typename Dtype>
      void func(int a, Dtype b)
      func(a, Scalar<Dtype>(std::move(b)));



      template argument deduction is pattern matching, and it only matches the types or their base types exactly. It does no conversion.



      Conversion is done later, at overload resolution & function call time.



      Here, we add another overload that explicitly forwards to the one you want.






      share|improve this answer






















        up vote
        1
        down vote










        up vote
        1
        down vote









        template<typename Dtype>
        void func(int a, Scalar<Dtype> b)
        cout << "ok" <<endl;

        template<typename Dtype>
        void func(int a, Dtype b)
        func(a, Scalar<Dtype>(std::move(b)));



        template argument deduction is pattern matching, and it only matches the types or their base types exactly. It does no conversion.



        Conversion is done later, at overload resolution & function call time.



        Here, we add another overload that explicitly forwards to the one you want.






        share|improve this answer












        template<typename Dtype>
        void func(int a, Scalar<Dtype> b)
        cout << "ok" <<endl;

        template<typename Dtype>
        void func(int a, Dtype b)
        func(a, Scalar<Dtype>(std::move(b)));



        template argument deduction is pattern matching, and it only matches the types or their base types exactly. It does no conversion.



        Conversion is done later, at overload resolution & function call time.



        Here, we add another overload that explicitly forwards to the one you want.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 55 mins ago









        Yakk - Adam Nevraumont

        176k19179361




        176k19179361



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53227713%2fwhy-does-the-implicit-type-conversion-not-work-in-template-deduction%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