Improvement for std::map double dispatch
I am trying to do my c++ homework and as a part of it I have to implement a std::map
with an int
as its key
and a value
should be a specific void
function, which prints some text.
I can`t find an answer to what are the correct ways of doing that.
This is what I have so far:
#include <map>
#include <string>
#include <iostream>
class testClass
{
public:
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
};
typedef void(testClass::*runFunc)(void);
typedef std::map<int, runFunc> myMapType;
int main() {
testClass t1;
std::map<int, runFunc> myMap;
myMap.emplace(1, &testClass::testFunc1);
myMap.emplace(2, &testClass::testFunc2);
myMapType::const_iterator itr;
itr = myMap.find(2);
if (itr != myMap.end()) {
(t1.*(itr->second))();
}
}
The code is working now, however I am not sure if that is the way people with more experience do.
Also, if you are aware of any sources where one can read more about knowledge required to achieve the needed result - any ideas are appreciated.
c++
New contributor
add a comment |
I am trying to do my c++ homework and as a part of it I have to implement a std::map
with an int
as its key
and a value
should be a specific void
function, which prints some text.
I can`t find an answer to what are the correct ways of doing that.
This is what I have so far:
#include <map>
#include <string>
#include <iostream>
class testClass
{
public:
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
};
typedef void(testClass::*runFunc)(void);
typedef std::map<int, runFunc> myMapType;
int main() {
testClass t1;
std::map<int, runFunc> myMap;
myMap.emplace(1, &testClass::testFunc1);
myMap.emplace(2, &testClass::testFunc2);
myMapType::const_iterator itr;
itr = myMap.find(2);
if (itr != myMap.end()) {
(t1.*(itr->second))();
}
}
The code is working now, however I am not sure if that is the way people with more experience do.
Also, if you are aware of any sources where one can read more about knowledge required to achieve the needed result - any ideas are appreciated.
c++
New contributor
1
If your code is a simplified version of what you really have to do, then it's off-topic and this question needs to be closed; per codereview.stackexchange.com/help/on-topic - "In order to give good advice, we need to see real, concrete code, and understand the context in which the code is used. Generic code (such as code containing placeholders like foo, MyClass, or doSomething()) leaves too much to the imagination."
– Reinderien
Dec 26 at 21:51
add a comment |
I am trying to do my c++ homework and as a part of it I have to implement a std::map
with an int
as its key
and a value
should be a specific void
function, which prints some text.
I can`t find an answer to what are the correct ways of doing that.
This is what I have so far:
#include <map>
#include <string>
#include <iostream>
class testClass
{
public:
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
};
typedef void(testClass::*runFunc)(void);
typedef std::map<int, runFunc> myMapType;
int main() {
testClass t1;
std::map<int, runFunc> myMap;
myMap.emplace(1, &testClass::testFunc1);
myMap.emplace(2, &testClass::testFunc2);
myMapType::const_iterator itr;
itr = myMap.find(2);
if (itr != myMap.end()) {
(t1.*(itr->second))();
}
}
The code is working now, however I am not sure if that is the way people with more experience do.
Also, if you are aware of any sources where one can read more about knowledge required to achieve the needed result - any ideas are appreciated.
c++
New contributor
I am trying to do my c++ homework and as a part of it I have to implement a std::map
with an int
as its key
and a value
should be a specific void
function, which prints some text.
I can`t find an answer to what are the correct ways of doing that.
This is what I have so far:
#include <map>
#include <string>
#include <iostream>
class testClass
{
public:
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
};
typedef void(testClass::*runFunc)(void);
typedef std::map<int, runFunc> myMapType;
int main() {
testClass t1;
std::map<int, runFunc> myMap;
myMap.emplace(1, &testClass::testFunc1);
myMap.emplace(2, &testClass::testFunc2);
myMapType::const_iterator itr;
itr = myMap.find(2);
if (itr != myMap.end()) {
(t1.*(itr->second))();
}
}
The code is working now, however I am not sure if that is the way people with more experience do.
Also, if you are aware of any sources where one can read more about knowledge required to achieve the needed result - any ideas are appreciated.
c++
c++
New contributor
New contributor
edited Dec 26 at 14:28
New contributor
asked Dec 26 at 13:01
Gasper J.
314
314
New contributor
New contributor
1
If your code is a simplified version of what you really have to do, then it's off-topic and this question needs to be closed; per codereview.stackexchange.com/help/on-topic - "In order to give good advice, we need to see real, concrete code, and understand the context in which the code is used. Generic code (such as code containing placeholders like foo, MyClass, or doSomething()) leaves too much to the imagination."
– Reinderien
Dec 26 at 21:51
add a comment |
1
If your code is a simplified version of what you really have to do, then it's off-topic and this question needs to be closed; per codereview.stackexchange.com/help/on-topic - "In order to give good advice, we need to see real, concrete code, and understand the context in which the code is used. Generic code (such as code containing placeholders like foo, MyClass, or doSomething()) leaves too much to the imagination."
– Reinderien
Dec 26 at 21:51
1
1
If your code is a simplified version of what you really have to do, then it's off-topic and this question needs to be closed; per codereview.stackexchange.com/help/on-topic - "In order to give good advice, we need to see real, concrete code, and understand the context in which the code is used. Generic code (such as code containing placeholders like foo, MyClass, or doSomething()) leaves too much to the imagination."
– Reinderien
Dec 26 at 21:51
If your code is a simplified version of what you really have to do, then it's off-topic and this question needs to be closed; per codereview.stackexchange.com/help/on-topic - "In order to give good advice, we need to see real, concrete code, and understand the context in which the code is used. Generic code (such as code containing placeholders like foo, MyClass, or doSomething()) leaves too much to the imagination."
– Reinderien
Dec 26 at 21:51
add a comment |
3 Answers
3
active
oldest
votes
As other answers have already said, the trick you're looking for is called std::function
, and it's defined in the standard <functional>
header.
You include <string>
but never use it. You define myMapType
but never use it.
Unless you need portability back to C++03, you should use using X = Y;
in place of typedef Y X;
.
A common name for "scratch" iterator variables is it
(not to be confused with i
for integer indices). Your itr
is reasonably clear, but not idiomatic.
Following the dictum that "good C++ code should look like Python," I'd write your program like this:
#include <cstdio>
#include <functional>
#include <map>
void testFunc1() {
puts("func1");
}
void testFunc2() {
puts("func2");
}
using MapType = std::map<int, std::function<void()>>;
int main() {
MapType myMap = {
{ 1, testFunc1 },
{ 2, testFunc2 },
};
auto it = myMap.find(2);
if (it != myMap.end()) {
it->second();
}
}
Instead of the map initializer I wrote, you could write
MapType myMap;
myMap[1] = testFunc1;
myMap[2] = testFunc2;
but I strongly recommend "declarative" over "imperative." "Declarative" style means to define the whole map at once, as a data object, in the state you want it; "imperative" style means to define an empty map and then repeatedly mutate it so as to eventually arrive at the state you want. "Declarative" tends to be easier to reason about.
add a comment |
In general your code looks good. But I have some little annotations (improvements) for you.
1. I'd prefer direct initialization of itr
for sake of readability:
myMapType::const_iterator itr = myMap.find(2);
instead of
myMapType::const_iterator itr;
itr = myMap.find(2);
That said you could also avoid
typedef std::map<int, runFunc> myMapType;
completely using the auto
keyword:
auto itr = myMap.find(2);
2. Make use std::function
and lambda bindings
For the callable value parameter of the std::map
I'd prefer to use an appropriate std::function
value type and lambda function bindings to the instance to operate on.
testClass t1;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&t1](){t1.testFunc1();});
myMap.emplace(2, [&t1](){t1.testFunc2();});
This will give you greater flexibility for later changes and use of other classes than just testClass
. Also you can get rid of that other type definition then:
typedef void(testClass::*runFunc)(void);
As soon you want to use your map for the general case you can clearly see the benefits:
class A {
public:
void print() { std::cout << "print() from class A.n"; }
};
class B {
public:
void print() { std::cout << "print() from class B.n"; }
};
// ...
int main() {
A a;
B b;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&a](){a.print();});
myMap.emplace(2, [&b](){b.print();});
}
Here's my set of changes in whole (you can check it's still working as intended here):
#include <map>
#include <string>
#include <iostream>
#include <functional>
class testClass
{
public:
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
};
int main() {
testClass t1;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&t1](){t1.testFunc1();});
myMap.emplace(2, [&t1](){t1.testFunc2();});
auto itr = myMap.find(2);
if (itr != myMap.end()) {
(itr->second)();
}
}
Instead of a lambda that calls the function you can use std::bind.
– Emily L.
Dec 26 at 15:55
2
@EmilyL. But lambdas are preferred overstd::bind
! There is no need for it now. Lambdas are far more expressive.
– Lightness Races in Orbit
Dec 27 at 2:33
@lightnessracesinorbit that's the first I've heard, can you give a reference? I still feel like bind is better expressing the intent
– Emily L.
Dec 27 at 12:24
2
@EmilyL. Sure! stackoverflow.com/a/17545183/560648
– Lightness Races in Orbit
Dec 27 at 14:02
add a comment |
Given your current test code, there's no reason for testClass
to exist. Your two test functions can simply be functions in the global namespace, and then your emplace
calls can be simplified.
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
typedef void(*runFunc)(void);
// ...
myMap.emplace(1, testFunc1);
myMap.emplace(2, testFunc2);
thanks for your suggestion. my code above is a simplified version of what I really have to do. with just global functions it won't go.
– Gasper J.
Dec 26 at 18:40
See comments on question, in that case. This is off-topic.
– Reinderien
Dec 26 at 21:52
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
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: "196"
};
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: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
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
});
}
});
Gasper J. is a new contributor. Be nice, and check out our Code of Conduct.
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%2fcodereview.stackexchange.com%2fquestions%2f210356%2fimprovement-for-stdmap-int-run-some-function-double-dispatch%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
As other answers have already said, the trick you're looking for is called std::function
, and it's defined in the standard <functional>
header.
You include <string>
but never use it. You define myMapType
but never use it.
Unless you need portability back to C++03, you should use using X = Y;
in place of typedef Y X;
.
A common name for "scratch" iterator variables is it
(not to be confused with i
for integer indices). Your itr
is reasonably clear, but not idiomatic.
Following the dictum that "good C++ code should look like Python," I'd write your program like this:
#include <cstdio>
#include <functional>
#include <map>
void testFunc1() {
puts("func1");
}
void testFunc2() {
puts("func2");
}
using MapType = std::map<int, std::function<void()>>;
int main() {
MapType myMap = {
{ 1, testFunc1 },
{ 2, testFunc2 },
};
auto it = myMap.find(2);
if (it != myMap.end()) {
it->second();
}
}
Instead of the map initializer I wrote, you could write
MapType myMap;
myMap[1] = testFunc1;
myMap[2] = testFunc2;
but I strongly recommend "declarative" over "imperative." "Declarative" style means to define the whole map at once, as a data object, in the state you want it; "imperative" style means to define an empty map and then repeatedly mutate it so as to eventually arrive at the state you want. "Declarative" tends to be easier to reason about.
add a comment |
As other answers have already said, the trick you're looking for is called std::function
, and it's defined in the standard <functional>
header.
You include <string>
but never use it. You define myMapType
but never use it.
Unless you need portability back to C++03, you should use using X = Y;
in place of typedef Y X;
.
A common name for "scratch" iterator variables is it
(not to be confused with i
for integer indices). Your itr
is reasonably clear, but not idiomatic.
Following the dictum that "good C++ code should look like Python," I'd write your program like this:
#include <cstdio>
#include <functional>
#include <map>
void testFunc1() {
puts("func1");
}
void testFunc2() {
puts("func2");
}
using MapType = std::map<int, std::function<void()>>;
int main() {
MapType myMap = {
{ 1, testFunc1 },
{ 2, testFunc2 },
};
auto it = myMap.find(2);
if (it != myMap.end()) {
it->second();
}
}
Instead of the map initializer I wrote, you could write
MapType myMap;
myMap[1] = testFunc1;
myMap[2] = testFunc2;
but I strongly recommend "declarative" over "imperative." "Declarative" style means to define the whole map at once, as a data object, in the state you want it; "imperative" style means to define an empty map and then repeatedly mutate it so as to eventually arrive at the state you want. "Declarative" tends to be easier to reason about.
add a comment |
As other answers have already said, the trick you're looking for is called std::function
, and it's defined in the standard <functional>
header.
You include <string>
but never use it. You define myMapType
but never use it.
Unless you need portability back to C++03, you should use using X = Y;
in place of typedef Y X;
.
A common name for "scratch" iterator variables is it
(not to be confused with i
for integer indices). Your itr
is reasonably clear, but not idiomatic.
Following the dictum that "good C++ code should look like Python," I'd write your program like this:
#include <cstdio>
#include <functional>
#include <map>
void testFunc1() {
puts("func1");
}
void testFunc2() {
puts("func2");
}
using MapType = std::map<int, std::function<void()>>;
int main() {
MapType myMap = {
{ 1, testFunc1 },
{ 2, testFunc2 },
};
auto it = myMap.find(2);
if (it != myMap.end()) {
it->second();
}
}
Instead of the map initializer I wrote, you could write
MapType myMap;
myMap[1] = testFunc1;
myMap[2] = testFunc2;
but I strongly recommend "declarative" over "imperative." "Declarative" style means to define the whole map at once, as a data object, in the state you want it; "imperative" style means to define an empty map and then repeatedly mutate it so as to eventually arrive at the state you want. "Declarative" tends to be easier to reason about.
As other answers have already said, the trick you're looking for is called std::function
, and it's defined in the standard <functional>
header.
You include <string>
but never use it. You define myMapType
but never use it.
Unless you need portability back to C++03, you should use using X = Y;
in place of typedef Y X;
.
A common name for "scratch" iterator variables is it
(not to be confused with i
for integer indices). Your itr
is reasonably clear, but not idiomatic.
Following the dictum that "good C++ code should look like Python," I'd write your program like this:
#include <cstdio>
#include <functional>
#include <map>
void testFunc1() {
puts("func1");
}
void testFunc2() {
puts("func2");
}
using MapType = std::map<int, std::function<void()>>;
int main() {
MapType myMap = {
{ 1, testFunc1 },
{ 2, testFunc2 },
};
auto it = myMap.find(2);
if (it != myMap.end()) {
it->second();
}
}
Instead of the map initializer I wrote, you could write
MapType myMap;
myMap[1] = testFunc1;
myMap[2] = testFunc2;
but I strongly recommend "declarative" over "imperative." "Declarative" style means to define the whole map at once, as a data object, in the state you want it; "imperative" style means to define an empty map and then repeatedly mutate it so as to eventually arrive at the state you want. "Declarative" tends to be easier to reason about.
answered Dec 27 at 2:06
Quuxplusone
11.3k11959
11.3k11959
add a comment |
add a comment |
In general your code looks good. But I have some little annotations (improvements) for you.
1. I'd prefer direct initialization of itr
for sake of readability:
myMapType::const_iterator itr = myMap.find(2);
instead of
myMapType::const_iterator itr;
itr = myMap.find(2);
That said you could also avoid
typedef std::map<int, runFunc> myMapType;
completely using the auto
keyword:
auto itr = myMap.find(2);
2. Make use std::function
and lambda bindings
For the callable value parameter of the std::map
I'd prefer to use an appropriate std::function
value type and lambda function bindings to the instance to operate on.
testClass t1;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&t1](){t1.testFunc1();});
myMap.emplace(2, [&t1](){t1.testFunc2();});
This will give you greater flexibility for later changes and use of other classes than just testClass
. Also you can get rid of that other type definition then:
typedef void(testClass::*runFunc)(void);
As soon you want to use your map for the general case you can clearly see the benefits:
class A {
public:
void print() { std::cout << "print() from class A.n"; }
};
class B {
public:
void print() { std::cout << "print() from class B.n"; }
};
// ...
int main() {
A a;
B b;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&a](){a.print();});
myMap.emplace(2, [&b](){b.print();});
}
Here's my set of changes in whole (you can check it's still working as intended here):
#include <map>
#include <string>
#include <iostream>
#include <functional>
class testClass
{
public:
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
};
int main() {
testClass t1;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&t1](){t1.testFunc1();});
myMap.emplace(2, [&t1](){t1.testFunc2();});
auto itr = myMap.find(2);
if (itr != myMap.end()) {
(itr->second)();
}
}
Instead of a lambda that calls the function you can use std::bind.
– Emily L.
Dec 26 at 15:55
2
@EmilyL. But lambdas are preferred overstd::bind
! There is no need for it now. Lambdas are far more expressive.
– Lightness Races in Orbit
Dec 27 at 2:33
@lightnessracesinorbit that's the first I've heard, can you give a reference? I still feel like bind is better expressing the intent
– Emily L.
Dec 27 at 12:24
2
@EmilyL. Sure! stackoverflow.com/a/17545183/560648
– Lightness Races in Orbit
Dec 27 at 14:02
add a comment |
In general your code looks good. But I have some little annotations (improvements) for you.
1. I'd prefer direct initialization of itr
for sake of readability:
myMapType::const_iterator itr = myMap.find(2);
instead of
myMapType::const_iterator itr;
itr = myMap.find(2);
That said you could also avoid
typedef std::map<int, runFunc> myMapType;
completely using the auto
keyword:
auto itr = myMap.find(2);
2. Make use std::function
and lambda bindings
For the callable value parameter of the std::map
I'd prefer to use an appropriate std::function
value type and lambda function bindings to the instance to operate on.
testClass t1;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&t1](){t1.testFunc1();});
myMap.emplace(2, [&t1](){t1.testFunc2();});
This will give you greater flexibility for later changes and use of other classes than just testClass
. Also you can get rid of that other type definition then:
typedef void(testClass::*runFunc)(void);
As soon you want to use your map for the general case you can clearly see the benefits:
class A {
public:
void print() { std::cout << "print() from class A.n"; }
};
class B {
public:
void print() { std::cout << "print() from class B.n"; }
};
// ...
int main() {
A a;
B b;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&a](){a.print();});
myMap.emplace(2, [&b](){b.print();});
}
Here's my set of changes in whole (you can check it's still working as intended here):
#include <map>
#include <string>
#include <iostream>
#include <functional>
class testClass
{
public:
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
};
int main() {
testClass t1;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&t1](){t1.testFunc1();});
myMap.emplace(2, [&t1](){t1.testFunc2();});
auto itr = myMap.find(2);
if (itr != myMap.end()) {
(itr->second)();
}
}
Instead of a lambda that calls the function you can use std::bind.
– Emily L.
Dec 26 at 15:55
2
@EmilyL. But lambdas are preferred overstd::bind
! There is no need for it now. Lambdas are far more expressive.
– Lightness Races in Orbit
Dec 27 at 2:33
@lightnessracesinorbit that's the first I've heard, can you give a reference? I still feel like bind is better expressing the intent
– Emily L.
Dec 27 at 12:24
2
@EmilyL. Sure! stackoverflow.com/a/17545183/560648
– Lightness Races in Orbit
Dec 27 at 14:02
add a comment |
In general your code looks good. But I have some little annotations (improvements) for you.
1. I'd prefer direct initialization of itr
for sake of readability:
myMapType::const_iterator itr = myMap.find(2);
instead of
myMapType::const_iterator itr;
itr = myMap.find(2);
That said you could also avoid
typedef std::map<int, runFunc> myMapType;
completely using the auto
keyword:
auto itr = myMap.find(2);
2. Make use std::function
and lambda bindings
For the callable value parameter of the std::map
I'd prefer to use an appropriate std::function
value type and lambda function bindings to the instance to operate on.
testClass t1;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&t1](){t1.testFunc1();});
myMap.emplace(2, [&t1](){t1.testFunc2();});
This will give you greater flexibility for later changes and use of other classes than just testClass
. Also you can get rid of that other type definition then:
typedef void(testClass::*runFunc)(void);
As soon you want to use your map for the general case you can clearly see the benefits:
class A {
public:
void print() { std::cout << "print() from class A.n"; }
};
class B {
public:
void print() { std::cout << "print() from class B.n"; }
};
// ...
int main() {
A a;
B b;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&a](){a.print();});
myMap.emplace(2, [&b](){b.print();});
}
Here's my set of changes in whole (you can check it's still working as intended here):
#include <map>
#include <string>
#include <iostream>
#include <functional>
class testClass
{
public:
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
};
int main() {
testClass t1;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&t1](){t1.testFunc1();});
myMap.emplace(2, [&t1](){t1.testFunc2();});
auto itr = myMap.find(2);
if (itr != myMap.end()) {
(itr->second)();
}
}
In general your code looks good. But I have some little annotations (improvements) for you.
1. I'd prefer direct initialization of itr
for sake of readability:
myMapType::const_iterator itr = myMap.find(2);
instead of
myMapType::const_iterator itr;
itr = myMap.find(2);
That said you could also avoid
typedef std::map<int, runFunc> myMapType;
completely using the auto
keyword:
auto itr = myMap.find(2);
2. Make use std::function
and lambda bindings
For the callable value parameter of the std::map
I'd prefer to use an appropriate std::function
value type and lambda function bindings to the instance to operate on.
testClass t1;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&t1](){t1.testFunc1();});
myMap.emplace(2, [&t1](){t1.testFunc2();});
This will give you greater flexibility for later changes and use of other classes than just testClass
. Also you can get rid of that other type definition then:
typedef void(testClass::*runFunc)(void);
As soon you want to use your map for the general case you can clearly see the benefits:
class A {
public:
void print() { std::cout << "print() from class A.n"; }
};
class B {
public:
void print() { std::cout << "print() from class B.n"; }
};
// ...
int main() {
A a;
B b;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&a](){a.print();});
myMap.emplace(2, [&b](){b.print();});
}
Here's my set of changes in whole (you can check it's still working as intended here):
#include <map>
#include <string>
#include <iostream>
#include <functional>
class testClass
{
public:
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
};
int main() {
testClass t1;
std::map<int, std::function<void()>> myMap;
myMap.emplace(1, [&t1](){t1.testFunc1();});
myMap.emplace(2, [&t1](){t1.testFunc2();});
auto itr = myMap.find(2);
if (itr != myMap.end()) {
(itr->second)();
}
}
edited Dec 26 at 15:05
answered Dec 26 at 14:02
πάντα ῥεῖ
3,91531328
3,91531328
Instead of a lambda that calls the function you can use std::bind.
– Emily L.
Dec 26 at 15:55
2
@EmilyL. But lambdas are preferred overstd::bind
! There is no need for it now. Lambdas are far more expressive.
– Lightness Races in Orbit
Dec 27 at 2:33
@lightnessracesinorbit that's the first I've heard, can you give a reference? I still feel like bind is better expressing the intent
– Emily L.
Dec 27 at 12:24
2
@EmilyL. Sure! stackoverflow.com/a/17545183/560648
– Lightness Races in Orbit
Dec 27 at 14:02
add a comment |
Instead of a lambda that calls the function you can use std::bind.
– Emily L.
Dec 26 at 15:55
2
@EmilyL. But lambdas are preferred overstd::bind
! There is no need for it now. Lambdas are far more expressive.
– Lightness Races in Orbit
Dec 27 at 2:33
@lightnessracesinorbit that's the first I've heard, can you give a reference? I still feel like bind is better expressing the intent
– Emily L.
Dec 27 at 12:24
2
@EmilyL. Sure! stackoverflow.com/a/17545183/560648
– Lightness Races in Orbit
Dec 27 at 14:02
Instead of a lambda that calls the function you can use std::bind.
– Emily L.
Dec 26 at 15:55
Instead of a lambda that calls the function you can use std::bind.
– Emily L.
Dec 26 at 15:55
2
2
@EmilyL. But lambdas are preferred over
std::bind
! There is no need for it now. Lambdas are far more expressive.– Lightness Races in Orbit
Dec 27 at 2:33
@EmilyL. But lambdas are preferred over
std::bind
! There is no need for it now. Lambdas are far more expressive.– Lightness Races in Orbit
Dec 27 at 2:33
@lightnessracesinorbit that's the first I've heard, can you give a reference? I still feel like bind is better expressing the intent
– Emily L.
Dec 27 at 12:24
@lightnessracesinorbit that's the first I've heard, can you give a reference? I still feel like bind is better expressing the intent
– Emily L.
Dec 27 at 12:24
2
2
@EmilyL. Sure! stackoverflow.com/a/17545183/560648
– Lightness Races in Orbit
Dec 27 at 14:02
@EmilyL. Sure! stackoverflow.com/a/17545183/560648
– Lightness Races in Orbit
Dec 27 at 14:02
add a comment |
Given your current test code, there's no reason for testClass
to exist. Your two test functions can simply be functions in the global namespace, and then your emplace
calls can be simplified.
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
typedef void(*runFunc)(void);
// ...
myMap.emplace(1, testFunc1);
myMap.emplace(2, testFunc2);
thanks for your suggestion. my code above is a simplified version of what I really have to do. with just global functions it won't go.
– Gasper J.
Dec 26 at 18:40
See comments on question, in that case. This is off-topic.
– Reinderien
Dec 26 at 21:52
add a comment |
Given your current test code, there's no reason for testClass
to exist. Your two test functions can simply be functions in the global namespace, and then your emplace
calls can be simplified.
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
typedef void(*runFunc)(void);
// ...
myMap.emplace(1, testFunc1);
myMap.emplace(2, testFunc2);
thanks for your suggestion. my code above is a simplified version of what I really have to do. with just global functions it won't go.
– Gasper J.
Dec 26 at 18:40
See comments on question, in that case. This is off-topic.
– Reinderien
Dec 26 at 21:52
add a comment |
Given your current test code, there's no reason for testClass
to exist. Your two test functions can simply be functions in the global namespace, and then your emplace
calls can be simplified.
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
typedef void(*runFunc)(void);
// ...
myMap.emplace(1, testFunc1);
myMap.emplace(2, testFunc2);
Given your current test code, there's no reason for testClass
to exist. Your two test functions can simply be functions in the global namespace, and then your emplace
calls can be simplified.
void testFunc1() { std::cout << "func1n"; }
void testFunc2() { std::cout << "func2n"; }
typedef void(*runFunc)(void);
// ...
myMap.emplace(1, testFunc1);
myMap.emplace(2, testFunc2);
answered Dec 26 at 17:54
Reinderien
3,299720
3,299720
thanks for your suggestion. my code above is a simplified version of what I really have to do. with just global functions it won't go.
– Gasper J.
Dec 26 at 18:40
See comments on question, in that case. This is off-topic.
– Reinderien
Dec 26 at 21:52
add a comment |
thanks for your suggestion. my code above is a simplified version of what I really have to do. with just global functions it won't go.
– Gasper J.
Dec 26 at 18:40
See comments on question, in that case. This is off-topic.
– Reinderien
Dec 26 at 21:52
thanks for your suggestion. my code above is a simplified version of what I really have to do. with just global functions it won't go.
– Gasper J.
Dec 26 at 18:40
thanks for your suggestion. my code above is a simplified version of what I really have to do. with just global functions it won't go.
– Gasper J.
Dec 26 at 18:40
See comments on question, in that case. This is off-topic.
– Reinderien
Dec 26 at 21:52
See comments on question, in that case. This is off-topic.
– Reinderien
Dec 26 at 21:52
add a comment |
Gasper J. is a new contributor. Be nice, and check out our Code of Conduct.
Gasper J. is a new contributor. Be nice, and check out our Code of Conduct.
Gasper J. is a new contributor. Be nice, and check out our Code of Conduct.
Gasper J. is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- 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.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2fcodereview.stackexchange.com%2fquestions%2f210356%2fimprovement-for-stdmap-int-run-some-function-double-dispatch%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
1
If your code is a simplified version of what you really have to do, then it's off-topic and this question needs to be closed; per codereview.stackexchange.com/help/on-topic - "In order to give good advice, we need to see real, concrete code, and understand the context in which the code is used. Generic code (such as code containing placeholders like foo, MyClass, or doSomething()) leaves too much to the imagination."
– Reinderien
Dec 26 at 21:51