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.4k74269




37.4k74269










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) : callbackcb0


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) : callbackcb0


    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) : callbackcb0


      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) : callbackcb0


        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) : callbackcb0


        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.4k74269




        37.4k74269





























            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







            這個網誌中的熱門文章

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

            In R, how to develop a multiplot heatmap.2 figure showing key labels successfully

            Museum of Modern and Contemporary Art of Trento and Rovereto