C++ template class with dynamic callback function type
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
add a comment |
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
As best as I can decipher this question, the subclass only needs to declare oneconsume()
method, with aT &
parameter, so that it overrides the equivalent method in the superclass (and the declaration should use theoverride
keyword instead ofvirtual
, 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 thatconsume(StateB&)
isn't generated, it's that it can't be compiled. InConsumer<StateA>
there is nocallback(StateB&)
, the only visiblecallback
takes aStateA&
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
add a comment |
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
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
c++ c++11 templates callback pure-virtual
edited Nov 15 '18 at 2:42
max66
37k74166
37k74166
asked Nov 15 '18 at 2:20
alekskaleksk
501413
501413
As best as I can decipher this question, the subclass only needs to declare oneconsume()
method, with aT &
parameter, so that it overrides the equivalent method in the superclass (and the declaration should use theoverride
keyword instead ofvirtual
, 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 thatconsume(StateB&)
isn't generated, it's that it can't be compiled. InConsumer<StateA>
there is nocallback(StateB&)
, the only visiblecallback
takes aStateA&
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
add a comment |
As best as I can decipher this question, the subclass only needs to declare oneconsume()
method, with aT &
parameter, so that it overrides the equivalent method in the superclass (and the declaration should use theoverride
keyword instead ofvirtual
, 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 thatconsume(StateB&)
isn't generated, it's that it can't be compiled. InConsumer<StateA>
there is nocallback(StateB&)
, the only visiblecallback
takes aStateA&
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
add a comment |
1 Answer
1
active
oldest
votes
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
}
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
}
add a comment |
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
}
add a comment |
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
}
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
}
edited Nov 15 '18 at 2:41
answered Nov 15 '18 at 2:35
max66max66
37k74166
37k74166
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
As best as I can decipher this question, the subclass only needs to declare one
consume()
method, with aT &
parameter, so that it overrides the equivalent method in the superclass (and the declaration should use theoverride
keyword instead ofvirtual
, 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. InConsumer<StateA>
there is nocallback(StateB&)
, the only visiblecallback
takes aStateA&
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