“multiple overloads” using templated class with duplicate types

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











up vote
8
down vote

favorite
1












I'm trying to write a class that takes two templated types. This class inherits from an interface. See the below code.



#include <iostream>
#include <string>

template <typename T>
class IObserver
public:
virtual void Next(const T& value) noexcept = 0;
;

template <typename T1, typename T2>
class BinaryObserver : public IObserver<T1>, public IObserver<T2>
public:
void Next(const T1& value) noexcept override;

void Next(const T2& value) noexcept override;
;

int main()
// This is OK
BinaryObserver<int, float> mc1;
mc1.Next(0);
mc1.Next(0.0f);

// This fails to compile with "multiple overloads"
BinaryObserver<int, int> mc2;
mc2.Next(0);
mc2.Next(0);



I'm having trouble when T1 is the same type as T2. Obviously this means two Next functions will be generated with the same type, which gives an error: multiple overloads of 'Next' instantiate to the same signature.



What's an idiomatic way of fixing this? I'm not sure how to handle the case when T1=T2 since I'd only need one Next function generated



Thanks!










share|improve this question



















  • 1




    It's not just the multiple overloads (which you can fix with some enable_if magic) but you are also deriving twice from the same base class which is also not allowed. @VTT's answer fixes both issues.
    – Alan Birtles
    Sep 22 at 17:43














up vote
8
down vote

favorite
1












I'm trying to write a class that takes two templated types. This class inherits from an interface. See the below code.



#include <iostream>
#include <string>

template <typename T>
class IObserver
public:
virtual void Next(const T& value) noexcept = 0;
;

template <typename T1, typename T2>
class BinaryObserver : public IObserver<T1>, public IObserver<T2>
public:
void Next(const T1& value) noexcept override;

void Next(const T2& value) noexcept override;
;

int main()
// This is OK
BinaryObserver<int, float> mc1;
mc1.Next(0);
mc1.Next(0.0f);

// This fails to compile with "multiple overloads"
BinaryObserver<int, int> mc2;
mc2.Next(0);
mc2.Next(0);



I'm having trouble when T1 is the same type as T2. Obviously this means two Next functions will be generated with the same type, which gives an error: multiple overloads of 'Next' instantiate to the same signature.



What's an idiomatic way of fixing this? I'm not sure how to handle the case when T1=T2 since I'd only need one Next function generated



Thanks!










share|improve this question



















  • 1




    It's not just the multiple overloads (which you can fix with some enable_if magic) but you are also deriving twice from the same base class which is also not allowed. @VTT's answer fixes both issues.
    – Alan Birtles
    Sep 22 at 17:43












up vote
8
down vote

favorite
1









up vote
8
down vote

favorite
1






1





I'm trying to write a class that takes two templated types. This class inherits from an interface. See the below code.



#include <iostream>
#include <string>

template <typename T>
class IObserver
public:
virtual void Next(const T& value) noexcept = 0;
;

template <typename T1, typename T2>
class BinaryObserver : public IObserver<T1>, public IObserver<T2>
public:
void Next(const T1& value) noexcept override;

void Next(const T2& value) noexcept override;
;

int main()
// This is OK
BinaryObserver<int, float> mc1;
mc1.Next(0);
mc1.Next(0.0f);

// This fails to compile with "multiple overloads"
BinaryObserver<int, int> mc2;
mc2.Next(0);
mc2.Next(0);



I'm having trouble when T1 is the same type as T2. Obviously this means two Next functions will be generated with the same type, which gives an error: multiple overloads of 'Next' instantiate to the same signature.



What's an idiomatic way of fixing this? I'm not sure how to handle the case when T1=T2 since I'd only need one Next function generated



Thanks!










share|improve this question















I'm trying to write a class that takes two templated types. This class inherits from an interface. See the below code.



#include <iostream>
#include <string>

template <typename T>
class IObserver
public:
virtual void Next(const T& value) noexcept = 0;
;

template <typename T1, typename T2>
class BinaryObserver : public IObserver<T1>, public IObserver<T2>
public:
void Next(const T1& value) noexcept override;

void Next(const T2& value) noexcept override;
;

int main()
// This is OK
BinaryObserver<int, float> mc1;
mc1.Next(0);
mc1.Next(0.0f);

// This fails to compile with "multiple overloads"
BinaryObserver<int, int> mc2;
mc2.Next(0);
mc2.Next(0);



I'm having trouble when T1 is the same type as T2. Obviously this means two Next functions will be generated with the same type, which gives an error: multiple overloads of 'Next' instantiate to the same signature.



What's an idiomatic way of fixing this? I'm not sure how to handle the case when T1=T2 since I'd only need one Next function generated



Thanks!







c++ c++11 templates overloading






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 22 at 16:42

























asked Sep 22 at 16:36









Sam P

1,418824




1,418824







  • 1




    It's not just the multiple overloads (which you can fix with some enable_if magic) but you are also deriving twice from the same base class which is also not allowed. @VTT's answer fixes both issues.
    – Alan Birtles
    Sep 22 at 17:43












  • 1




    It's not just the multiple overloads (which you can fix with some enable_if magic) but you are also deriving twice from the same base class which is also not allowed. @VTT's answer fixes both issues.
    – Alan Birtles
    Sep 22 at 17:43







1




1




It's not just the multiple overloads (which you can fix with some enable_if magic) but you are also deriving twice from the same base class which is also not allowed. @VTT's answer fixes both issues.
– Alan Birtles
Sep 22 at 17:43




It's not just the multiple overloads (which you can fix with some enable_if magic) but you are also deriving twice from the same base class which is also not allowed. @VTT's answer fixes both issues.
– Alan Birtles
Sep 22 at 17:43












2 Answers
2






active

oldest

votes

















up vote
14
down vote



accepted










How about a specialization:



template <typename T>
class BinaryObserver<T, T> : public IObserver<T>
public:
void Next(const T & value) noexcept override;
;





share|improve this answer




















  • Exactly what I needed, thank you!
    – Sam P
    Sep 24 at 17:36

















up vote
0
down vote













You have another issue in your program:



BinaryObserver<int, int> mc2;
mc2.Next(0);
mc2.Next(0);


Which one of the Next you expect the compiler would choose in case you succeed?
In the VIT's answer you will have only a sigle Next implemented in specification and calling it twice will do something different.



So, the best solution is to have different IObserver classes with different function names to overload, i.e



class BinaryObserver : public IObserver<T1>, public IObserver1<T2> 
...
mc2.Next(0);
mc2.Next1(0);


Another possibility is to put one of Ts in another container. I used Shell struct in this example:



template
struct Shell
T t;
Shell(T t): t(t)
operator T() const return t;
;



template <typename T1, typename T2>
class BinaryObserver : public IObserver<T1>, public IObserver<Shell<T2>>
public:
void Next(const T1& value) noexcept overrideT1 t = value;;
void Next(const Shell<T2>& value) noexcept overrideT2 t = value;;
;

...

BinaryObserver<int, float> mc1;
mc1.Next(0);
mc1.Next(0.0f);

BinaryObserver<int, int> mc2;
mc2.Next(0);
mc2.Next(Shell<int>(0));





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



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52458675%2fmultiple-overloads-using-templated-class-with-duplicate-types%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
    14
    down vote



    accepted










    How about a specialization:



    template <typename T>
    class BinaryObserver<T, T> : public IObserver<T>
    public:
    void Next(const T & value) noexcept override;
    ;





    share|improve this answer




















    • Exactly what I needed, thank you!
      – Sam P
      Sep 24 at 17:36














    up vote
    14
    down vote



    accepted










    How about a specialization:



    template <typename T>
    class BinaryObserver<T, T> : public IObserver<T>
    public:
    void Next(const T & value) noexcept override;
    ;





    share|improve this answer




















    • Exactly what I needed, thank you!
      – Sam P
      Sep 24 at 17:36












    up vote
    14
    down vote



    accepted







    up vote
    14
    down vote



    accepted






    How about a specialization:



    template <typename T>
    class BinaryObserver<T, T> : public IObserver<T>
    public:
    void Next(const T & value) noexcept override;
    ;





    share|improve this answer












    How about a specialization:



    template <typename T>
    class BinaryObserver<T, T> : public IObserver<T>
    public:
    void Next(const T & value) noexcept override;
    ;






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Sep 22 at 16:43









    VTT

    21.8k32345




    21.8k32345











    • Exactly what I needed, thank you!
      – Sam P
      Sep 24 at 17:36
















    • Exactly what I needed, thank you!
      – Sam P
      Sep 24 at 17:36















    Exactly what I needed, thank you!
    – Sam P
    Sep 24 at 17:36




    Exactly what I needed, thank you!
    – Sam P
    Sep 24 at 17:36












    up vote
    0
    down vote













    You have another issue in your program:



    BinaryObserver<int, int> mc2;
    mc2.Next(0);
    mc2.Next(0);


    Which one of the Next you expect the compiler would choose in case you succeed?
    In the VIT's answer you will have only a sigle Next implemented in specification and calling it twice will do something different.



    So, the best solution is to have different IObserver classes with different function names to overload, i.e



    class BinaryObserver : public IObserver<T1>, public IObserver1<T2> 
    ...
    mc2.Next(0);
    mc2.Next1(0);


    Another possibility is to put one of Ts in another container. I used Shell struct in this example:



    template
    struct Shell
    T t;
    Shell(T t): t(t)
    operator T() const return t;
    ;



    template <typename T1, typename T2>
    class BinaryObserver : public IObserver<T1>, public IObserver<Shell<T2>>
    public:
    void Next(const T1& value) noexcept overrideT1 t = value;;
    void Next(const Shell<T2>& value) noexcept overrideT2 t = value;;
    ;

    ...

    BinaryObserver<int, float> mc1;
    mc1.Next(0);
    mc1.Next(0.0f);

    BinaryObserver<int, int> mc2;
    mc2.Next(0);
    mc2.Next(Shell<int>(0));





    share|improve this answer
























      up vote
      0
      down vote













      You have another issue in your program:



      BinaryObserver<int, int> mc2;
      mc2.Next(0);
      mc2.Next(0);


      Which one of the Next you expect the compiler would choose in case you succeed?
      In the VIT's answer you will have only a sigle Next implemented in specification and calling it twice will do something different.



      So, the best solution is to have different IObserver classes with different function names to overload, i.e



      class BinaryObserver : public IObserver<T1>, public IObserver1<T2> 
      ...
      mc2.Next(0);
      mc2.Next1(0);


      Another possibility is to put one of Ts in another container. I used Shell struct in this example:



      template
      struct Shell
      T t;
      Shell(T t): t(t)
      operator T() const return t;
      ;



      template <typename T1, typename T2>
      class BinaryObserver : public IObserver<T1>, public IObserver<Shell<T2>>
      public:
      void Next(const T1& value) noexcept overrideT1 t = value;;
      void Next(const Shell<T2>& value) noexcept overrideT2 t = value;;
      ;

      ...

      BinaryObserver<int, float> mc1;
      mc1.Next(0);
      mc1.Next(0.0f);

      BinaryObserver<int, int> mc2;
      mc2.Next(0);
      mc2.Next(Shell<int>(0));





      share|improve this answer






















        up vote
        0
        down vote










        up vote
        0
        down vote









        You have another issue in your program:



        BinaryObserver<int, int> mc2;
        mc2.Next(0);
        mc2.Next(0);


        Which one of the Next you expect the compiler would choose in case you succeed?
        In the VIT's answer you will have only a sigle Next implemented in specification and calling it twice will do something different.



        So, the best solution is to have different IObserver classes with different function names to overload, i.e



        class BinaryObserver : public IObserver<T1>, public IObserver1<T2> 
        ...
        mc2.Next(0);
        mc2.Next1(0);


        Another possibility is to put one of Ts in another container. I used Shell struct in this example:



        template
        struct Shell
        T t;
        Shell(T t): t(t)
        operator T() const return t;
        ;



        template <typename T1, typename T2>
        class BinaryObserver : public IObserver<T1>, public IObserver<Shell<T2>>
        public:
        void Next(const T1& value) noexcept overrideT1 t = value;;
        void Next(const Shell<T2>& value) noexcept overrideT2 t = value;;
        ;

        ...

        BinaryObserver<int, float> mc1;
        mc1.Next(0);
        mc1.Next(0.0f);

        BinaryObserver<int, int> mc2;
        mc2.Next(0);
        mc2.Next(Shell<int>(0));





        share|improve this answer












        You have another issue in your program:



        BinaryObserver<int, int> mc2;
        mc2.Next(0);
        mc2.Next(0);


        Which one of the Next you expect the compiler would choose in case you succeed?
        In the VIT's answer you will have only a sigle Next implemented in specification and calling it twice will do something different.



        So, the best solution is to have different IObserver classes with different function names to overload, i.e



        class BinaryObserver : public IObserver<T1>, public IObserver1<T2> 
        ...
        mc2.Next(0);
        mc2.Next1(0);


        Another possibility is to put one of Ts in another container. I used Shell struct in this example:



        template
        struct Shell
        T t;
        Shell(T t): t(t)
        operator T() const return t;
        ;



        template <typename T1, typename T2>
        class BinaryObserver : public IObserver<T1>, public IObserver<Shell<T2>>
        public:
        void Next(const T1& value) noexcept overrideT1 t = value;;
        void Next(const Shell<T2>& value) noexcept overrideT2 t = value;;
        ;

        ...

        BinaryObserver<int, float> mc1;
        mc1.Next(0);
        mc1.Next(0.0f);

        BinaryObserver<int, int> mc2;
        mc2.Next(0);
        mc2.Next(Shell<int>(0));






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Sep 22 at 19:48









        Serge

        2,6902912




        2,6902912



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52458675%2fmultiple-overloads-using-templated-class-with-duplicate-types%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Displaying single band from multi-band raster using QGIS

            How many registers does an x86_64 CPU actually have?