C++ template class with dynamic callback function type












0















In the code below, I want a user to be able to create a consumer class with a specific type, eg Consumer<StateA> so their callback function can correctly handle the type they give it. However in the code below, the compiler complains because at compile time, the call to the function in the StateB consume method is not generated. The consume methods come from a base class and they have to be overriden.



template <class T>
class Consumer : ConsumerBase
{
public:
Consumer(std::function<void(T&)> _callback){
callback = _callback;
}
virtual void consume(StateA& state) {
callback(state);
}
virtual void consume(StateB& state) {
callback(state);
}
private:
std::function<void(T&)> callback;
};


Base Class:



class ConsumerBase
{
public:
virtual void consume(StateA& state) = 0;
virtual void consume(StateB& state) = 0;
};


How can I make this work?










share|improve this question

























  • As best as I can decipher this question, the subclass only needs to declare one consume() method, with a T & parameter, so that it overrides the equivalent method in the superclass (and the declaration should use the override keyword instead of virtual, in order to help your compiler catch bugs in your code). If the superclass defines only abstract methods, a different approach will be needed, however since your question lacks a Minimal, Complete, and Verifiable example, as explained in stackoverflow.com's help center, no further suggestions are possible.

    – Sam Varshavchik
    Nov 15 '18 at 2:28











  • @SamVarshavchik thanks, I have added the base class, which has pure virtual functions that have to have overrides.

    – aleksk
    Nov 15 '18 at 2:34











  • I suspect it's not that consume(StateB&) isn't generated, it's that it can't be compiled. In Consumer<StateA> there is no callback(StateB&), the only visible callback takes a StateA& so you can't compile the definition.

    – jthill
    Nov 15 '18 at 2:49











  • @jthill yes, you are correct. I meant to say the call to the (callback) function cannot be found (by the compiler) because there is no callback function generated with StateB.

    – aleksk
    Nov 15 '18 at 2:54


















0















In the code below, I want a user to be able to create a consumer class with a specific type, eg Consumer<StateA> so their callback function can correctly handle the type they give it. However in the code below, the compiler complains because at compile time, the call to the function in the StateB consume method is not generated. The consume methods come from a base class and they have to be overriden.



template <class T>
class Consumer : ConsumerBase
{
public:
Consumer(std::function<void(T&)> _callback){
callback = _callback;
}
virtual void consume(StateA& state) {
callback(state);
}
virtual void consume(StateB& state) {
callback(state);
}
private:
std::function<void(T&)> callback;
};


Base Class:



class ConsumerBase
{
public:
virtual void consume(StateA& state) = 0;
virtual void consume(StateB& state) = 0;
};


How can I make this work?










share|improve this question

























  • As best as I can decipher this question, the subclass only needs to declare one consume() method, with a T & parameter, so that it overrides the equivalent method in the superclass (and the declaration should use the override keyword instead of virtual, in order to help your compiler catch bugs in your code). If the superclass defines only abstract methods, a different approach will be needed, however since your question lacks a Minimal, Complete, and Verifiable example, as explained in stackoverflow.com's help center, no further suggestions are possible.

    – Sam Varshavchik
    Nov 15 '18 at 2:28











  • @SamVarshavchik thanks, I have added the base class, which has pure virtual functions that have to have overrides.

    – aleksk
    Nov 15 '18 at 2:34











  • I suspect it's not that consume(StateB&) isn't generated, it's that it can't be compiled. In Consumer<StateA> there is no callback(StateB&), the only visible callback takes a StateA& so you can't compile the definition.

    – jthill
    Nov 15 '18 at 2:49











  • @jthill yes, you are correct. I meant to say the call to the (callback) function cannot be found (by the compiler) because there is no callback function generated with StateB.

    – aleksk
    Nov 15 '18 at 2:54
















0












0








0








In the code below, I want a user to be able to create a consumer class with a specific type, eg Consumer<StateA> so their callback function can correctly handle the type they give it. However in the code below, the compiler complains because at compile time, the call to the function in the StateB consume method is not generated. The consume methods come from a base class and they have to be overriden.



template <class T>
class Consumer : ConsumerBase
{
public:
Consumer(std::function<void(T&)> _callback){
callback = _callback;
}
virtual void consume(StateA& state) {
callback(state);
}
virtual void consume(StateB& state) {
callback(state);
}
private:
std::function<void(T&)> callback;
};


Base Class:



class ConsumerBase
{
public:
virtual void consume(StateA& state) = 0;
virtual void consume(StateB& state) = 0;
};


How can I make this work?










share|improve this question
















In the code below, I want a user to be able to create a consumer class with a specific type, eg Consumer<StateA> so their callback function can correctly handle the type they give it. However in the code below, the compiler complains because at compile time, the call to the function in the StateB consume method is not generated. The consume methods come from a base class and they have to be overriden.



template <class T>
class Consumer : ConsumerBase
{
public:
Consumer(std::function<void(T&)> _callback){
callback = _callback;
}
virtual void consume(StateA& state) {
callback(state);
}
virtual void consume(StateB& state) {
callback(state);
}
private:
std::function<void(T&)> callback;
};


Base Class:



class ConsumerBase
{
public:
virtual void consume(StateA& state) = 0;
virtual void consume(StateB& state) = 0;
};


How can I make this work?







c++ c++11 templates callback pure-virtual






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 15 '18 at 2:42









max66

37.1k74166




37.1k74166










asked Nov 15 '18 at 2:20









alekskaleksk

501413




501413













  • As best as I can decipher this question, the subclass only needs to declare one consume() method, with a T & parameter, so that it overrides the equivalent method in the superclass (and the declaration should use the override keyword instead of virtual, in order to help your compiler catch bugs in your code). If the superclass defines only abstract methods, a different approach will be needed, however since your question lacks a Minimal, Complete, and Verifiable example, as explained in stackoverflow.com's help center, no further suggestions are possible.

    – Sam Varshavchik
    Nov 15 '18 at 2:28











  • @SamVarshavchik thanks, I have added the base class, which has pure virtual functions that have to have overrides.

    – aleksk
    Nov 15 '18 at 2:34











  • I suspect it's not that consume(StateB&) isn't generated, it's that it can't be compiled. In Consumer<StateA> there is no callback(StateB&), the only visible callback takes a StateA& so you can't compile the definition.

    – jthill
    Nov 15 '18 at 2:49











  • @jthill yes, you are correct. I meant to say the call to the (callback) function cannot be found (by the compiler) because there is no callback function generated with StateB.

    – aleksk
    Nov 15 '18 at 2:54





















  • As best as I can decipher this question, the subclass only needs to declare one consume() method, with a T & parameter, so that it overrides the equivalent method in the superclass (and the declaration should use the override keyword instead of virtual, in order to help your compiler catch bugs in your code). If the superclass defines only abstract methods, a different approach will be needed, however since your question lacks a Minimal, Complete, and Verifiable example, as explained in stackoverflow.com's help center, no further suggestions are possible.

    – Sam Varshavchik
    Nov 15 '18 at 2:28











  • @SamVarshavchik thanks, I have added the base class, which has pure virtual functions that have to have overrides.

    – aleksk
    Nov 15 '18 at 2:34











  • I suspect it's not that consume(StateB&) isn't generated, it's that it can't be compiled. In Consumer<StateA> there is no callback(StateB&), the only visible callback takes a StateA& so you can't compile the definition.

    – jthill
    Nov 15 '18 at 2:49











  • @jthill yes, you are correct. I meant to say the call to the (callback) function cannot be found (by the compiler) because there is no callback function generated with StateB.

    – aleksk
    Nov 15 '18 at 2:54



















As best as I can decipher this question, the subclass only needs to declare one consume() method, with a T & parameter, so that it overrides the equivalent method in the superclass (and the declaration should use the override keyword instead of virtual, in order to help your compiler catch bugs in your code). If the superclass defines only abstract methods, a different approach will be needed, however since your question lacks a Minimal, Complete, and Verifiable example, as explained in stackoverflow.com's help center, no further suggestions are possible.

– Sam Varshavchik
Nov 15 '18 at 2:28





As best as I can decipher this question, the subclass only needs to declare one consume() method, with a T & parameter, so that it overrides the equivalent method in the superclass (and the declaration should use the override keyword instead of virtual, in order to help your compiler catch bugs in your code). If the superclass defines only abstract methods, a different approach will be needed, however since your question lacks a Minimal, Complete, and Verifiable example, as explained in stackoverflow.com's help center, no further suggestions are possible.

– Sam Varshavchik
Nov 15 '18 at 2:28













@SamVarshavchik thanks, I have added the base class, which has pure virtual functions that have to have overrides.

– aleksk
Nov 15 '18 at 2:34





@SamVarshavchik thanks, I have added the base class, which has pure virtual functions that have to have overrides.

– aleksk
Nov 15 '18 at 2:34













I suspect it's not that consume(StateB&) isn't generated, it's that it can't be compiled. In Consumer<StateA> there is no callback(StateB&), the only visible callback takes a StateA& so you can't compile the definition.

– jthill
Nov 15 '18 at 2:49





I suspect it's not that consume(StateB&) isn't generated, it's that it can't be compiled. In Consumer<StateA> there is no callback(StateB&), the only visible callback takes a StateA& so you can't compile the definition.

– jthill
Nov 15 '18 at 2:49













@jthill yes, you are correct. I meant to say the call to the (callback) function cannot be found (by the compiler) because there is no callback function generated with StateB.

– aleksk
Nov 15 '18 at 2:54







@jthill yes, you are correct. I meant to say the call to the (callback) function cannot be found (by the compiler) because there is no callback function generated with StateB.

– aleksk
Nov 15 '18 at 2:54














1 Answer
1






active

oldest

votes


















2















The consume methods come from a base class and they have to be overriden. [...] How can I make this work?




I suppose that a possible solution is develop a couple of consume_h() ("consume helper") methods.



The first one is an exact match for T (the template type of the class) that call the callback function



    void consume_h (T & state)
{ callback(state); }


The second one is a template version that do nothing



    template <typename U>
void consume_h (U &)
{ }


Now you can override both virtual method calling consume_h()



    virtual void consume (StateA & state)
{ consume_h(state); }

virtual void consume (StateB & state)
{ consume_h(state); }


This way the virtual method corresponding to T, call the consume_h() that call the callback; the other call the template consume_h() that do nothing.



The following is a full compiling example



#include <functional>

struct StateA { };
struct StateB { };

struct ConsumerBase
{
virtual void consume (StateA &) = 0;
virtual void consume (StateB &) = 0;
};

template <typename T>
class Consumer : ConsumerBase
{
public:
Consumer (std::function<void(T&)> cb0) : callback{cb0}
{ }

void consume_h (T & state)
{ callback(state); }

template <typename U>
void consume_h (U &)
{ }

virtual void consume (StateA & state)
{ consume_h(state); }

virtual void consume (StateB & state)
{ consume_h(state); }

private:
std::function<void(T&)> callback;
};

int main()
{
Consumer<StateA> csa{(StateA &){ std::cout << "A" << std::endl; }};
Consumer<StateB> csb{(StateB &){ std::cout << "B" << std::endl; }};

StateA sa;
StateB sb;

csa.consume(sa); // print A
csb.consume(sb); // print B
}





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%2f53311513%2fc-template-class-with-dynamic-callback-function-type%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









    2















    The consume methods come from a base class and they have to be overriden. [...] How can I make this work?




    I suppose that a possible solution is develop a couple of consume_h() ("consume helper") methods.



    The first one is an exact match for T (the template type of the class) that call the callback function



        void consume_h (T & state)
    { callback(state); }


    The second one is a template version that do nothing



        template <typename U>
    void consume_h (U &)
    { }


    Now you can override both virtual method calling consume_h()



        virtual void consume (StateA & state)
    { consume_h(state); }

    virtual void consume (StateB & state)
    { consume_h(state); }


    This way the virtual method corresponding to T, call the consume_h() that call the callback; the other call the template consume_h() that do nothing.



    The following is a full compiling example



    #include <functional>

    struct StateA { };
    struct StateB { };

    struct ConsumerBase
    {
    virtual void consume (StateA &) = 0;
    virtual void consume (StateB &) = 0;
    };

    template <typename T>
    class Consumer : ConsumerBase
    {
    public:
    Consumer (std::function<void(T&)> cb0) : callback{cb0}
    { }

    void consume_h (T & state)
    { callback(state); }

    template <typename U>
    void consume_h (U &)
    { }

    virtual void consume (StateA & state)
    { consume_h(state); }

    virtual void consume (StateB & state)
    { consume_h(state); }

    private:
    std::function<void(T&)> callback;
    };

    int main()
    {
    Consumer<StateA> csa{(StateA &){ std::cout << "A" << std::endl; }};
    Consumer<StateB> csb{(StateB &){ std::cout << "B" << std::endl; }};

    StateA sa;
    StateB sb;

    csa.consume(sa); // print A
    csb.consume(sb); // print B
    }





    share|improve this answer






























      2















      The consume methods come from a base class and they have to be overriden. [...] How can I make this work?




      I suppose that a possible solution is develop a couple of consume_h() ("consume helper") methods.



      The first one is an exact match for T (the template type of the class) that call the callback function



          void consume_h (T & state)
      { callback(state); }


      The second one is a template version that do nothing



          template <typename U>
      void consume_h (U &)
      { }


      Now you can override both virtual method calling consume_h()



          virtual void consume (StateA & state)
      { consume_h(state); }

      virtual void consume (StateB & state)
      { consume_h(state); }


      This way the virtual method corresponding to T, call the consume_h() that call the callback; the other call the template consume_h() that do nothing.



      The following is a full compiling example



      #include <functional>

      struct StateA { };
      struct StateB { };

      struct ConsumerBase
      {
      virtual void consume (StateA &) = 0;
      virtual void consume (StateB &) = 0;
      };

      template <typename T>
      class Consumer : ConsumerBase
      {
      public:
      Consumer (std::function<void(T&)> cb0) : callback{cb0}
      { }

      void consume_h (T & state)
      { callback(state); }

      template <typename U>
      void consume_h (U &)
      { }

      virtual void consume (StateA & state)
      { consume_h(state); }

      virtual void consume (StateB & state)
      { consume_h(state); }

      private:
      std::function<void(T&)> callback;
      };

      int main()
      {
      Consumer<StateA> csa{(StateA &){ std::cout << "A" << std::endl; }};
      Consumer<StateB> csb{(StateB &){ std::cout << "B" << std::endl; }};

      StateA sa;
      StateB sb;

      csa.consume(sa); // print A
      csb.consume(sb); // print B
      }





      share|improve this answer




























        2












        2








        2








        The consume methods come from a base class and they have to be overriden. [...] How can I make this work?




        I suppose that a possible solution is develop a couple of consume_h() ("consume helper") methods.



        The first one is an exact match for T (the template type of the class) that call the callback function



            void consume_h (T & state)
        { callback(state); }


        The second one is a template version that do nothing



            template <typename U>
        void consume_h (U &)
        { }


        Now you can override both virtual method calling consume_h()



            virtual void consume (StateA & state)
        { consume_h(state); }

        virtual void consume (StateB & state)
        { consume_h(state); }


        This way the virtual method corresponding to T, call the consume_h() that call the callback; the other call the template consume_h() that do nothing.



        The following is a full compiling example



        #include <functional>

        struct StateA { };
        struct StateB { };

        struct ConsumerBase
        {
        virtual void consume (StateA &) = 0;
        virtual void consume (StateB &) = 0;
        };

        template <typename T>
        class Consumer : ConsumerBase
        {
        public:
        Consumer (std::function<void(T&)> cb0) : callback{cb0}
        { }

        void consume_h (T & state)
        { callback(state); }

        template <typename U>
        void consume_h (U &)
        { }

        virtual void consume (StateA & state)
        { consume_h(state); }

        virtual void consume (StateB & state)
        { consume_h(state); }

        private:
        std::function<void(T&)> callback;
        };

        int main()
        {
        Consumer<StateA> csa{(StateA &){ std::cout << "A" << std::endl; }};
        Consumer<StateB> csb{(StateB &){ std::cout << "B" << std::endl; }};

        StateA sa;
        StateB sb;

        csa.consume(sa); // print A
        csb.consume(sb); // print B
        }





        share|improve this answer
















        The consume methods come from a base class and they have to be overriden. [...] How can I make this work?




        I suppose that a possible solution is develop a couple of consume_h() ("consume helper") methods.



        The first one is an exact match for T (the template type of the class) that call the callback function



            void consume_h (T & state)
        { callback(state); }


        The second one is a template version that do nothing



            template <typename U>
        void consume_h (U &)
        { }


        Now you can override both virtual method calling consume_h()



            virtual void consume (StateA & state)
        { consume_h(state); }

        virtual void consume (StateB & state)
        { consume_h(state); }


        This way the virtual method corresponding to T, call the consume_h() that call the callback; the other call the template consume_h() that do nothing.



        The following is a full compiling example



        #include <functional>

        struct StateA { };
        struct StateB { };

        struct ConsumerBase
        {
        virtual void consume (StateA &) = 0;
        virtual void consume (StateB &) = 0;
        };

        template <typename T>
        class Consumer : ConsumerBase
        {
        public:
        Consumer (std::function<void(T&)> cb0) : callback{cb0}
        { }

        void consume_h (T & state)
        { callback(state); }

        template <typename U>
        void consume_h (U &)
        { }

        virtual void consume (StateA & state)
        { consume_h(state); }

        virtual void consume (StateB & state)
        { consume_h(state); }

        private:
        std::function<void(T&)> callback;
        };

        int main()
        {
        Consumer<StateA> csa{(StateA &){ std::cout << "A" << std::endl; }};
        Consumer<StateB> csb{(StateB &){ std::cout << "B" << std::endl; }};

        StateA sa;
        StateB sb;

        csa.consume(sa); // print A
        csb.consume(sb); // print B
        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 15 '18 at 2:41

























        answered Nov 15 '18 at 2:35









        max66max66

        37.1k74166




        37.1k74166
































            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%2f53311513%2fc-template-class-with-dynamic-callback-function-type%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







            Popular posts from this blog

            Florida Star v. B. J. F.

            Danny Elfman

            Lugert, Oklahoma