How to specialize templated operator overloads?










1















I'm trying to overload comparison operators as non-members for a particular templated class sub, 1) between instances of sub, and 2) between sub and a specific variable, which returns an instance of either comparer_sub for the first case and comparer_el in the alternative, which perform comparisons on sub along with some other useful members:



template <typename T1, typename T2>
class sub_base
public:
sub_base() ;
;

template <typename T>
class mat
class sub : public sub_base<T,mat<T>>
public:
sub(): sub_base<T,mat<T>>() ;
;
public:
int mb;
sub getSub() return sub();;
;

template <typename T1,typename T2>
class comparer_base
public:
comparer_base() ;
void base_method() ;
;

template <typename lT1,typename lT2,typename rT1,typename rT2>
class comparer_sub : public comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>
using comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>::base_method;
public:
comparer_sub() : comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>() ;
;

template <typename lT1,typename lT2,typename rT>
class comparer_el : public comparer_base<sub_base<lT1,lT2>,rT>
using comparer_base<sub_base<lT1,lT2>,rT>::base_method;
public:
comparer_el() : comparer_base<sub_base<lT1,lT2>,rT>() ;
;

template <typename lT1,typename lT2,typename rT1,typename rT2>
comparer_sub<lT1,lT2,rT1,rT2> operator== (const sub_base<lT1,lT2>& lhs, const sub_base<rT1,rT2>& rhs)
printf("comparer_subn");
return comparer_sub<lT1,lT2,rT1,rT2>();
;
template <typename lT1,typename lT2,typename rT>
comparer_el<lT1,lT2,rT> operator== (const sub_base<lT1,lT2>& lhs, const rT& rhs)
printf("comparer_eln");
return comparer_el<lT1,lT2,rT>();
;


However, any type of comparison I try to perform the second overload is called, what I assume is due to const rt& being too generic and any instance of sub fits that argument.



int main(int argc, char const *argv) 
mat<int> A;
mat<float> B;
float C = 0.6;

A.getSub() == B.getSub(); // comparer_el
A.getSub() == C; // comparer_el

return 0;



How can I force the first overload to be prioritized over the second overload between instances of sub??










share|improve this question
























  • @user1810087 I've edited the question, needed to call getSub() on comparison types.

    – joaocandre
    Nov 13 '18 at 15:30











  • now it does compile :) BTW, i did not downvote your question... counter +1, because the question is interesting...

    – user1810087
    Nov 13 '18 at 15:36












  • Cannot put it into good words right now, but the problem is, comparer_el with the second parameter beeing substituted from sub to typename rT2 is a better choise as the substitution+cast from sub to sub_base<rT1,rT2>. Substitution does not implicitly cast... So, one solution is not to use return type sub with getSub() but the base type sub_base<rT1,rT2>. see here, only change line 22

    – user1810087
    Nov 13 '18 at 15:50












  • Also, return type sub_base<rT1,rT2> should be prefered as class sub is nested and only known inside class mat...

    – user1810087
    Nov 13 '18 at 15:59











  • Fair enough, I think I've understood the problem. The whole reason I nested class sub was to simplify the syntax and avoid trailing template arguments (the actual code is quite cluttered and hard to "read" as it is) - would a templated typedef work in this case?

    – joaocandre
    Nov 13 '18 at 16:04















1















I'm trying to overload comparison operators as non-members for a particular templated class sub, 1) between instances of sub, and 2) between sub and a specific variable, which returns an instance of either comparer_sub for the first case and comparer_el in the alternative, which perform comparisons on sub along with some other useful members:



template <typename T1, typename T2>
class sub_base
public:
sub_base() ;
;

template <typename T>
class mat
class sub : public sub_base<T,mat<T>>
public:
sub(): sub_base<T,mat<T>>() ;
;
public:
int mb;
sub getSub() return sub();;
;

template <typename T1,typename T2>
class comparer_base
public:
comparer_base() ;
void base_method() ;
;

template <typename lT1,typename lT2,typename rT1,typename rT2>
class comparer_sub : public comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>
using comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>::base_method;
public:
comparer_sub() : comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>() ;
;

template <typename lT1,typename lT2,typename rT>
class comparer_el : public comparer_base<sub_base<lT1,lT2>,rT>
using comparer_base<sub_base<lT1,lT2>,rT>::base_method;
public:
comparer_el() : comparer_base<sub_base<lT1,lT2>,rT>() ;
;

template <typename lT1,typename lT2,typename rT1,typename rT2>
comparer_sub<lT1,lT2,rT1,rT2> operator== (const sub_base<lT1,lT2>& lhs, const sub_base<rT1,rT2>& rhs)
printf("comparer_subn");
return comparer_sub<lT1,lT2,rT1,rT2>();
;
template <typename lT1,typename lT2,typename rT>
comparer_el<lT1,lT2,rT> operator== (const sub_base<lT1,lT2>& lhs, const rT& rhs)
printf("comparer_eln");
return comparer_el<lT1,lT2,rT>();
;


However, any type of comparison I try to perform the second overload is called, what I assume is due to const rt& being too generic and any instance of sub fits that argument.



int main(int argc, char const *argv) 
mat<int> A;
mat<float> B;
float C = 0.6;

A.getSub() == B.getSub(); // comparer_el
A.getSub() == C; // comparer_el

return 0;



How can I force the first overload to be prioritized over the second overload between instances of sub??










share|improve this question
























  • @user1810087 I've edited the question, needed to call getSub() on comparison types.

    – joaocandre
    Nov 13 '18 at 15:30











  • now it does compile :) BTW, i did not downvote your question... counter +1, because the question is interesting...

    – user1810087
    Nov 13 '18 at 15:36












  • Cannot put it into good words right now, but the problem is, comparer_el with the second parameter beeing substituted from sub to typename rT2 is a better choise as the substitution+cast from sub to sub_base<rT1,rT2>. Substitution does not implicitly cast... So, one solution is not to use return type sub with getSub() but the base type sub_base<rT1,rT2>. see here, only change line 22

    – user1810087
    Nov 13 '18 at 15:50












  • Also, return type sub_base<rT1,rT2> should be prefered as class sub is nested and only known inside class mat...

    – user1810087
    Nov 13 '18 at 15:59











  • Fair enough, I think I've understood the problem. The whole reason I nested class sub was to simplify the syntax and avoid trailing template arguments (the actual code is quite cluttered and hard to "read" as it is) - would a templated typedef work in this case?

    – joaocandre
    Nov 13 '18 at 16:04













1












1








1








I'm trying to overload comparison operators as non-members for a particular templated class sub, 1) between instances of sub, and 2) between sub and a specific variable, which returns an instance of either comparer_sub for the first case and comparer_el in the alternative, which perform comparisons on sub along with some other useful members:



template <typename T1, typename T2>
class sub_base
public:
sub_base() ;
;

template <typename T>
class mat
class sub : public sub_base<T,mat<T>>
public:
sub(): sub_base<T,mat<T>>() ;
;
public:
int mb;
sub getSub() return sub();;
;

template <typename T1,typename T2>
class comparer_base
public:
comparer_base() ;
void base_method() ;
;

template <typename lT1,typename lT2,typename rT1,typename rT2>
class comparer_sub : public comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>
using comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>::base_method;
public:
comparer_sub() : comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>() ;
;

template <typename lT1,typename lT2,typename rT>
class comparer_el : public comparer_base<sub_base<lT1,lT2>,rT>
using comparer_base<sub_base<lT1,lT2>,rT>::base_method;
public:
comparer_el() : comparer_base<sub_base<lT1,lT2>,rT>() ;
;

template <typename lT1,typename lT2,typename rT1,typename rT2>
comparer_sub<lT1,lT2,rT1,rT2> operator== (const sub_base<lT1,lT2>& lhs, const sub_base<rT1,rT2>& rhs)
printf("comparer_subn");
return comparer_sub<lT1,lT2,rT1,rT2>();
;
template <typename lT1,typename lT2,typename rT>
comparer_el<lT1,lT2,rT> operator== (const sub_base<lT1,lT2>& lhs, const rT& rhs)
printf("comparer_eln");
return comparer_el<lT1,lT2,rT>();
;


However, any type of comparison I try to perform the second overload is called, what I assume is due to const rt& being too generic and any instance of sub fits that argument.



int main(int argc, char const *argv) 
mat<int> A;
mat<float> B;
float C = 0.6;

A.getSub() == B.getSub(); // comparer_el
A.getSub() == C; // comparer_el

return 0;



How can I force the first overload to be prioritized over the second overload between instances of sub??










share|improve this question
















I'm trying to overload comparison operators as non-members for a particular templated class sub, 1) between instances of sub, and 2) between sub and a specific variable, which returns an instance of either comparer_sub for the first case and comparer_el in the alternative, which perform comparisons on sub along with some other useful members:



template <typename T1, typename T2>
class sub_base
public:
sub_base() ;
;

template <typename T>
class mat
class sub : public sub_base<T,mat<T>>
public:
sub(): sub_base<T,mat<T>>() ;
;
public:
int mb;
sub getSub() return sub();;
;

template <typename T1,typename T2>
class comparer_base
public:
comparer_base() ;
void base_method() ;
;

template <typename lT1,typename lT2,typename rT1,typename rT2>
class comparer_sub : public comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>
using comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>::base_method;
public:
comparer_sub() : comparer_base<sub_base<lT1,lT2>,sub_base<rT1,rT2>>() ;
;

template <typename lT1,typename lT2,typename rT>
class comparer_el : public comparer_base<sub_base<lT1,lT2>,rT>
using comparer_base<sub_base<lT1,lT2>,rT>::base_method;
public:
comparer_el() : comparer_base<sub_base<lT1,lT2>,rT>() ;
;

template <typename lT1,typename lT2,typename rT1,typename rT2>
comparer_sub<lT1,lT2,rT1,rT2> operator== (const sub_base<lT1,lT2>& lhs, const sub_base<rT1,rT2>& rhs)
printf("comparer_subn");
return comparer_sub<lT1,lT2,rT1,rT2>();
;
template <typename lT1,typename lT2,typename rT>
comparer_el<lT1,lT2,rT> operator== (const sub_base<lT1,lT2>& lhs, const rT& rhs)
printf("comparer_eln");
return comparer_el<lT1,lT2,rT>();
;


However, any type of comparison I try to perform the second overload is called, what I assume is due to const rt& being too generic and any instance of sub fits that argument.



int main(int argc, char const *argv) 
mat<int> A;
mat<float> B;
float C = 0.6;

A.getSub() == B.getSub(); // comparer_el
A.getSub() == C; // comparer_el

return 0;



How can I force the first overload to be prioritized over the second overload between instances of sub??







c++ templates operator-overloading






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 15:29







joaocandre

















asked Nov 13 '18 at 15:15









joaocandrejoaocandre

4921023




4921023












  • @user1810087 I've edited the question, needed to call getSub() on comparison types.

    – joaocandre
    Nov 13 '18 at 15:30











  • now it does compile :) BTW, i did not downvote your question... counter +1, because the question is interesting...

    – user1810087
    Nov 13 '18 at 15:36












  • Cannot put it into good words right now, but the problem is, comparer_el with the second parameter beeing substituted from sub to typename rT2 is a better choise as the substitution+cast from sub to sub_base<rT1,rT2>. Substitution does not implicitly cast... So, one solution is not to use return type sub with getSub() but the base type sub_base<rT1,rT2>. see here, only change line 22

    – user1810087
    Nov 13 '18 at 15:50












  • Also, return type sub_base<rT1,rT2> should be prefered as class sub is nested and only known inside class mat...

    – user1810087
    Nov 13 '18 at 15:59











  • Fair enough, I think I've understood the problem. The whole reason I nested class sub was to simplify the syntax and avoid trailing template arguments (the actual code is quite cluttered and hard to "read" as it is) - would a templated typedef work in this case?

    – joaocandre
    Nov 13 '18 at 16:04

















  • @user1810087 I've edited the question, needed to call getSub() on comparison types.

    – joaocandre
    Nov 13 '18 at 15:30











  • now it does compile :) BTW, i did not downvote your question... counter +1, because the question is interesting...

    – user1810087
    Nov 13 '18 at 15:36












  • Cannot put it into good words right now, but the problem is, comparer_el with the second parameter beeing substituted from sub to typename rT2 is a better choise as the substitution+cast from sub to sub_base<rT1,rT2>. Substitution does not implicitly cast... So, one solution is not to use return type sub with getSub() but the base type sub_base<rT1,rT2>. see here, only change line 22

    – user1810087
    Nov 13 '18 at 15:50












  • Also, return type sub_base<rT1,rT2> should be prefered as class sub is nested and only known inside class mat...

    – user1810087
    Nov 13 '18 at 15:59











  • Fair enough, I think I've understood the problem. The whole reason I nested class sub was to simplify the syntax and avoid trailing template arguments (the actual code is quite cluttered and hard to "read" as it is) - would a templated typedef work in this case?

    – joaocandre
    Nov 13 '18 at 16:04
















@user1810087 I've edited the question, needed to call getSub() on comparison types.

– joaocandre
Nov 13 '18 at 15:30





@user1810087 I've edited the question, needed to call getSub() on comparison types.

– joaocandre
Nov 13 '18 at 15:30













now it does compile :) BTW, i did not downvote your question... counter +1, because the question is interesting...

– user1810087
Nov 13 '18 at 15:36






now it does compile :) BTW, i did not downvote your question... counter +1, because the question is interesting...

– user1810087
Nov 13 '18 at 15:36














Cannot put it into good words right now, but the problem is, comparer_el with the second parameter beeing substituted from sub to typename rT2 is a better choise as the substitution+cast from sub to sub_base<rT1,rT2>. Substitution does not implicitly cast... So, one solution is not to use return type sub with getSub() but the base type sub_base<rT1,rT2>. see here, only change line 22

– user1810087
Nov 13 '18 at 15:50






Cannot put it into good words right now, but the problem is, comparer_el with the second parameter beeing substituted from sub to typename rT2 is a better choise as the substitution+cast from sub to sub_base<rT1,rT2>. Substitution does not implicitly cast... So, one solution is not to use return type sub with getSub() but the base type sub_base<rT1,rT2>. see here, only change line 22

– user1810087
Nov 13 '18 at 15:50














Also, return type sub_base<rT1,rT2> should be prefered as class sub is nested and only known inside class mat...

– user1810087
Nov 13 '18 at 15:59





Also, return type sub_base<rT1,rT2> should be prefered as class sub is nested and only known inside class mat...

– user1810087
Nov 13 '18 at 15:59













Fair enough, I think I've understood the problem. The whole reason I nested class sub was to simplify the syntax and avoid trailing template arguments (the actual code is quite cluttered and hard to "read" as it is) - would a templated typedef work in this case?

– joaocandre
Nov 13 '18 at 16:04





Fair enough, I think I've understood the problem. The whole reason I nested class sub was to simplify the syntax and avoid trailing template arguments (the actual code is quite cluttered and hard to "read" as it is) - would a templated typedef work in this case?

– joaocandre
Nov 13 '18 at 16:04












1 Answer
1






active

oldest

votes


















1














The problem is, comparer_el with rT=sub is a better choise than the substitution+cast from sub to sub_base<rT1,rT2>. Deduction does not implicitly cast (except putting additional c/v qualifiers)... For a much better description, read this answer.



So, one solution is not to use return type sub within getSub() but the base type sub_base<rT1,rT2>. see here



important part:



template <typename T>
class mat
class sub : public sub_base<T,mat<T>>
public:
sub(): sub_base<T,mat<T>>() ;
;
public:
int mb;
sub_base<T,mat<T>> getSub() return sub();;
// ^^^^^^^^^^^^^^^^^^ return type changed from sub to sub_base<T,mat<T>>
;





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',
    autoActivateHeartbeat: false,
    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%2f53284069%2fhow-to-specialize-templated-operator-overloads%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    The problem is, comparer_el with rT=sub is a better choise than the substitution+cast from sub to sub_base<rT1,rT2>. Deduction does not implicitly cast (except putting additional c/v qualifiers)... For a much better description, read this answer.



    So, one solution is not to use return type sub within getSub() but the base type sub_base<rT1,rT2>. see here



    important part:



    template <typename T>
    class mat
    class sub : public sub_base<T,mat<T>>
    public:
    sub(): sub_base<T,mat<T>>() ;
    ;
    public:
    int mb;
    sub_base<T,mat<T>> getSub() return sub();;
    // ^^^^^^^^^^^^^^^^^^ return type changed from sub to sub_base<T,mat<T>>
    ;





    share|improve this answer



























      1














      The problem is, comparer_el with rT=sub is a better choise than the substitution+cast from sub to sub_base<rT1,rT2>. Deduction does not implicitly cast (except putting additional c/v qualifiers)... For a much better description, read this answer.



      So, one solution is not to use return type sub within getSub() but the base type sub_base<rT1,rT2>. see here



      important part:



      template <typename T>
      class mat
      class sub : public sub_base<T,mat<T>>
      public:
      sub(): sub_base<T,mat<T>>() ;
      ;
      public:
      int mb;
      sub_base<T,mat<T>> getSub() return sub();;
      // ^^^^^^^^^^^^^^^^^^ return type changed from sub to sub_base<T,mat<T>>
      ;





      share|improve this answer

























        1












        1








        1







        The problem is, comparer_el with rT=sub is a better choise than the substitution+cast from sub to sub_base<rT1,rT2>. Deduction does not implicitly cast (except putting additional c/v qualifiers)... For a much better description, read this answer.



        So, one solution is not to use return type sub within getSub() but the base type sub_base<rT1,rT2>. see here



        important part:



        template <typename T>
        class mat
        class sub : public sub_base<T,mat<T>>
        public:
        sub(): sub_base<T,mat<T>>() ;
        ;
        public:
        int mb;
        sub_base<T,mat<T>> getSub() return sub();;
        // ^^^^^^^^^^^^^^^^^^ return type changed from sub to sub_base<T,mat<T>>
        ;





        share|improve this answer













        The problem is, comparer_el with rT=sub is a better choise than the substitution+cast from sub to sub_base<rT1,rT2>. Deduction does not implicitly cast (except putting additional c/v qualifiers)... For a much better description, read this answer.



        So, one solution is not to use return type sub within getSub() but the base type sub_base<rT1,rT2>. see here



        important part:



        template <typename T>
        class mat
        class sub : public sub_base<T,mat<T>>
        public:
        sub(): sub_base<T,mat<T>>() ;
        ;
        public:
        int mb;
        sub_base<T,mat<T>> getSub() return sub();;
        // ^^^^^^^^^^^^^^^^^^ return type changed from sub to sub_base<T,mat<T>>
        ;






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 13 '18 at 16:27









        user1810087user1810087

        2,60312450




        2,60312450



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53284069%2fhow-to-specialize-templated-operator-overloads%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







            這個網誌中的熱門文章

            Barbados

            How to read a connectionString WITH PROVIDER in .NET Core?

            Node.js Script on GitHub Pages or Amazon S3