Pass a member function as Compare operator for C++ standard library algorithm
In my code I have now something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
[&bar](Foo const &lhs, Foo const &rhs) {
return bar.myWeakLessOperator(lhs, rhs);
});
I wonder wether it exists a way to simplify it by passing directly the member function myWeakLessOperator
(that is not static) instead of writing a lambda function just to make to call.
I would like to obtain something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
/* something that rely to */ bar.myWeakLessOperator);
Any idea if it possible and how to do it ?
c++ c++11 standard-library
|
show 5 more comments
In my code I have now something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
[&bar](Foo const &lhs, Foo const &rhs) {
return bar.myWeakLessOperator(lhs, rhs);
});
I wonder wether it exists a way to simplify it by passing directly the member function myWeakLessOperator
(that is not static) instead of writing a lambda function just to make to call.
I would like to obtain something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
/* something that rely to */ bar.myWeakLessOperator);
Any idea if it possible and how to do it ?
c++ c++11 standard-library
withstd::bind(&Foo::myWeakLessOperator, std::placeholders::_1, std::placeholders::_1, std::placeholders::_2)
you can get away withbar
, but why not just make a static version ?
– Piotr Skotnicki
Nov 15 '18 at 17:56
@PiotrSkotnicki in that case OP may just remove the first parameter frommyWeakLessOperator
altogether since it's justthis
duplicated.
– Pezo
Nov 15 '18 at 17:58
1
@Azias could you elaborate on whatmyWeakLessOperator
does, why is it a member function when it seems to compare two unrelated objects?
– Pezo
Nov 15 '18 at 18:00
I cannot have a static version because the result of myWeakLessOperator will depend on the object. Actually my operator compares two objects against their distance to a main object (myWeakLessOperator
could be renamedClosestThan
).bar
is the main object, and my final goal with std::min_element is to find the element frommySet' that is the closest to
bar`
– Azias
Nov 15 '18 at 18:15
Then my answer is not a solution unfortunately, what you want is basically a bound member function. I had a need for this a couple days ago, but couldn't find anything, so I wrote my own. I'm trying to recreate it just now.
– Pezo
Nov 15 '18 at 18:21
|
show 5 more comments
In my code I have now something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
[&bar](Foo const &lhs, Foo const &rhs) {
return bar.myWeakLessOperator(lhs, rhs);
});
I wonder wether it exists a way to simplify it by passing directly the member function myWeakLessOperator
(that is not static) instead of writing a lambda function just to make to call.
I would like to obtain something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
/* something that rely to */ bar.myWeakLessOperator);
Any idea if it possible and how to do it ?
c++ c++11 standard-library
In my code I have now something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
[&bar](Foo const &lhs, Foo const &rhs) {
return bar.myWeakLessOperator(lhs, rhs);
});
I wonder wether it exists a way to simplify it by passing directly the member function myWeakLessOperator
(that is not static) instead of writing a lambda function just to make to call.
I would like to obtain something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
/* something that rely to */ bar.myWeakLessOperator);
Any idea if it possible and how to do it ?
c++ c++11 standard-library
c++ c++11 standard-library
edited Nov 15 '18 at 18:16
HolyBlackCat
16.8k33468
16.8k33468
asked Nov 15 '18 at 17:45
AziasAzias
11418
11418
withstd::bind(&Foo::myWeakLessOperator, std::placeholders::_1, std::placeholders::_1, std::placeholders::_2)
you can get away withbar
, but why not just make a static version ?
– Piotr Skotnicki
Nov 15 '18 at 17:56
@PiotrSkotnicki in that case OP may just remove the first parameter frommyWeakLessOperator
altogether since it's justthis
duplicated.
– Pezo
Nov 15 '18 at 17:58
1
@Azias could you elaborate on whatmyWeakLessOperator
does, why is it a member function when it seems to compare two unrelated objects?
– Pezo
Nov 15 '18 at 18:00
I cannot have a static version because the result of myWeakLessOperator will depend on the object. Actually my operator compares two objects against their distance to a main object (myWeakLessOperator
could be renamedClosestThan
).bar
is the main object, and my final goal with std::min_element is to find the element frommySet' that is the closest to
bar`
– Azias
Nov 15 '18 at 18:15
Then my answer is not a solution unfortunately, what you want is basically a bound member function. I had a need for this a couple days ago, but couldn't find anything, so I wrote my own. I'm trying to recreate it just now.
– Pezo
Nov 15 '18 at 18:21
|
show 5 more comments
withstd::bind(&Foo::myWeakLessOperator, std::placeholders::_1, std::placeholders::_1, std::placeholders::_2)
you can get away withbar
, but why not just make a static version ?
– Piotr Skotnicki
Nov 15 '18 at 17:56
@PiotrSkotnicki in that case OP may just remove the first parameter frommyWeakLessOperator
altogether since it's justthis
duplicated.
– Pezo
Nov 15 '18 at 17:58
1
@Azias could you elaborate on whatmyWeakLessOperator
does, why is it a member function when it seems to compare two unrelated objects?
– Pezo
Nov 15 '18 at 18:00
I cannot have a static version because the result of myWeakLessOperator will depend on the object. Actually my operator compares two objects against their distance to a main object (myWeakLessOperator
could be renamedClosestThan
).bar
is the main object, and my final goal with std::min_element is to find the element frommySet' that is the closest to
bar`
– Azias
Nov 15 '18 at 18:15
Then my answer is not a solution unfortunately, what you want is basically a bound member function. I had a need for this a couple days ago, but couldn't find anything, so I wrote my own. I'm trying to recreate it just now.
– Pezo
Nov 15 '18 at 18:21
with
std::bind(&Foo::myWeakLessOperator, std::placeholders::_1, std::placeholders::_1, std::placeholders::_2)
you can get away with bar
, but why not just make a static version ?– Piotr Skotnicki
Nov 15 '18 at 17:56
with
std::bind(&Foo::myWeakLessOperator, std::placeholders::_1, std::placeholders::_1, std::placeholders::_2)
you can get away with bar
, but why not just make a static version ?– Piotr Skotnicki
Nov 15 '18 at 17:56
@PiotrSkotnicki in that case OP may just remove the first parameter from
myWeakLessOperator
altogether since it's just this
duplicated.– Pezo
Nov 15 '18 at 17:58
@PiotrSkotnicki in that case OP may just remove the first parameter from
myWeakLessOperator
altogether since it's just this
duplicated.– Pezo
Nov 15 '18 at 17:58
1
1
@Azias could you elaborate on what
myWeakLessOperator
does, why is it a member function when it seems to compare two unrelated objects?– Pezo
Nov 15 '18 at 18:00
@Azias could you elaborate on what
myWeakLessOperator
does, why is it a member function when it seems to compare two unrelated objects?– Pezo
Nov 15 '18 at 18:00
I cannot have a static version because the result of myWeakLessOperator will depend on the object. Actually my operator compares two objects against their distance to a main object (
myWeakLessOperator
could be renamed ClosestThan
). bar
is the main object, and my final goal with std::min_element is to find the element from mySet' that is the closest to
bar`– Azias
Nov 15 '18 at 18:15
I cannot have a static version because the result of myWeakLessOperator will depend on the object. Actually my operator compares two objects against their distance to a main object (
myWeakLessOperator
could be renamed ClosestThan
). bar
is the main object, and my final goal with std::min_element is to find the element from mySet' that is the closest to
bar`– Azias
Nov 15 '18 at 18:15
Then my answer is not a solution unfortunately, what you want is basically a bound member function. I had a need for this a couple days ago, but couldn't find anything, so I wrote my own. I'm trying to recreate it just now.
– Pezo
Nov 15 '18 at 18:21
Then my answer is not a solution unfortunately, what you want is basically a bound member function. I had a need for this a couple days ago, but couldn't find anything, so I wrote my own. I'm trying to recreate it just now.
– Pezo
Nov 15 '18 at 18:21
|
show 5 more comments
4 Answers
4
active
oldest
votes
A possible solution is to use a struct that satisfies Compare inside Foo:
class Foo
{
public:
struct WeakLessOperator
{
bool operator()(const Foo& a, const Foo& b)
{
// implementation - take care of meeting requirements of Compare
return true;
}
};
WeakLessOperator myWeakLessOperator;
};
Foo bar;
auto minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
bar.myWeakLessOperator);
add a comment |
So you want to have a function object that represents a member function bound to a particular receiver. Unfortunately, there's nothing I could find in the standard or Boost that does that.
What you can do is write your own fairly easily.
template <typename R, typename T>
struct member_function_binder {
T *receiver;
R T::*pmf;
template <typename... Args>
auto operator()(Args&&... args) {
return (receiver->*pmf)(std::forward<Args>(args)...);
}
};
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return member_function_binder<R, T>{&receiver, pmf};
}
Have a look at the live demo, I think this might be what you want.
Even more concise, you don't need to have a separate class member_function_binder
if you return a lambda from bind_member_function
like so:
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return [pmf, &receiver](auto&&... args) {
return (receiver.*pmf)(std::forward<decltype(args)>(args)...);
};
}
Live demo
Solution to pass a unary member function like Foo::compareTo(const Foo &rhs)
, not what OP asked:
What you want is std::mem_fn
; it's a wrapper that makes a member function pointer into a function object. You would use it like this:
auto min = std::min_element(
begin(mySet), end(mySet), std::mem_fn(&Foo::myWeakLessOperator));
myWeakLessOperator
is a 2-parameter member function
– Piotr Skotnicki
Nov 15 '18 at 17:55
@PiotrSkotnicki I just noticed that too, that doesn't seem very sensible though.
– Pezo
Nov 15 '18 at 17:56
I don't think this would work, as you need 3 parameters to invoke the wrapper properly in this example.
– user1095108
Nov 15 '18 at 17:56
add a comment |
you can use std::bind
, or some other wrapper.
EXAMPLE:
using namespace std::placeholders;
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
std::bind(&Foo::myWeakLessOperator, bar, _1, _2));
OR
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
gnr::memfun<MEMFUN(Foo::myWeakLessOperator)>(bar));
Can you give an example, I am not used tostd::bind
and co, I cannot see how to use it.
– Azias
Nov 15 '18 at 18:30
Lambda is superior to everything, though, faster, takes up less space, ...
– user1095108
Nov 15 '18 at 18:53
I have tried with this example and it effectively does the job. thanks.
– Azias
Nov 16 '18 at 8:01
You should know thatstd::bind
is a lambda precursor. Effectively, the lambda replaces it and is superior.
– user1095108
Nov 16 '18 at 12:24
add a comment |
The closest to what you want is maybe
auto minElement =
std::min_element(
std::begin(mySet),
std::end(mySet),
mem_fun_functor(&Foo::myWeakLessOperator)
);
There is std::mem_fun
(deprecated in c++11) and std::mem_fn
both wrap a member function pointer, though both take a instance as parameter to invoke the member function. If you want a functor that wraps the object also, i think you need to write your own:
auto mem_fun_functor =
[&bar](decltype(&Foo::myWeakLessOperator) f){
return [f,&bar](const Foo& a,const Foo& b) {
return (bar.*f)(a,b);
};
};
However, given that none of the answers is really much shorter or leading to cleaner code, I would consider to just use your first version with the lambda (unless you maybe have many different member functions that you want to use as comparator).
What do you actually mean by "simplifying" ? You do need to specify the object you want to call the member function on, you need to specify how you want to forward the parameters. Thats basically all the lambda does.
Defering all this to a functor as for example above makes your code more complicated rather than simpler. In your first snippet anybody familiar with standard algorithms can look at that few lines of code and fully understand what is going on.
Eventually it is a matter of style, and what you consider as readable, but being able to declare stuff in the most narrowest scope is one big advantage of using lambdas.
Correction:std::mem_fun
was deprecated long ago and removed in C++17, you shouldn't use that.std::mem_fn
is the way to go, it takes both references and pointers (raw or smart) as receivers.
– Pezo
Nov 15 '18 at 20:51
@Pezo thanks, corrected
– user463035818
Nov 15 '18 at 20:54
I really like your idea of returning a lambda, I never think of that.
– Pezo
Nov 15 '18 at 20:56
@Pezo my favourite is mjdmochowski's answer, though I really think just writing the lambda directly in the algorithm call is the most clean way. Its a bit of typing, but I prever to have everything in the most narrow scope. Whether there are reasons to pull something to a higher scope isnt really clear from the question
– user463035818
Nov 15 '18 at 21:00
I don't particularly like that solution since it'll waste space, because you need a reference/pointer to the containing object in the operator object (so it can access members).
– Pezo
Nov 16 '18 at 11:05
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%2f53325193%2fpass-a-member-function-as-compare-operator-for-c-standard-library-algorithm%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
A possible solution is to use a struct that satisfies Compare inside Foo:
class Foo
{
public:
struct WeakLessOperator
{
bool operator()(const Foo& a, const Foo& b)
{
// implementation - take care of meeting requirements of Compare
return true;
}
};
WeakLessOperator myWeakLessOperator;
};
Foo bar;
auto minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
bar.myWeakLessOperator);
add a comment |
A possible solution is to use a struct that satisfies Compare inside Foo:
class Foo
{
public:
struct WeakLessOperator
{
bool operator()(const Foo& a, const Foo& b)
{
// implementation - take care of meeting requirements of Compare
return true;
}
};
WeakLessOperator myWeakLessOperator;
};
Foo bar;
auto minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
bar.myWeakLessOperator);
add a comment |
A possible solution is to use a struct that satisfies Compare inside Foo:
class Foo
{
public:
struct WeakLessOperator
{
bool operator()(const Foo& a, const Foo& b)
{
// implementation - take care of meeting requirements of Compare
return true;
}
};
WeakLessOperator myWeakLessOperator;
};
Foo bar;
auto minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
bar.myWeakLessOperator);
A possible solution is to use a struct that satisfies Compare inside Foo:
class Foo
{
public:
struct WeakLessOperator
{
bool operator()(const Foo& a, const Foo& b)
{
// implementation - take care of meeting requirements of Compare
return true;
}
};
WeakLessOperator myWeakLessOperator;
};
Foo bar;
auto minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
bar.myWeakLessOperator);
edited Nov 15 '18 at 18:14
answered Nov 15 '18 at 18:06
mjdmochowskimjdmochowski
213
213
add a comment |
add a comment |
So you want to have a function object that represents a member function bound to a particular receiver. Unfortunately, there's nothing I could find in the standard or Boost that does that.
What you can do is write your own fairly easily.
template <typename R, typename T>
struct member_function_binder {
T *receiver;
R T::*pmf;
template <typename... Args>
auto operator()(Args&&... args) {
return (receiver->*pmf)(std::forward<Args>(args)...);
}
};
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return member_function_binder<R, T>{&receiver, pmf};
}
Have a look at the live demo, I think this might be what you want.
Even more concise, you don't need to have a separate class member_function_binder
if you return a lambda from bind_member_function
like so:
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return [pmf, &receiver](auto&&... args) {
return (receiver.*pmf)(std::forward<decltype(args)>(args)...);
};
}
Live demo
Solution to pass a unary member function like Foo::compareTo(const Foo &rhs)
, not what OP asked:
What you want is std::mem_fn
; it's a wrapper that makes a member function pointer into a function object. You would use it like this:
auto min = std::min_element(
begin(mySet), end(mySet), std::mem_fn(&Foo::myWeakLessOperator));
myWeakLessOperator
is a 2-parameter member function
– Piotr Skotnicki
Nov 15 '18 at 17:55
@PiotrSkotnicki I just noticed that too, that doesn't seem very sensible though.
– Pezo
Nov 15 '18 at 17:56
I don't think this would work, as you need 3 parameters to invoke the wrapper properly in this example.
– user1095108
Nov 15 '18 at 17:56
add a comment |
So you want to have a function object that represents a member function bound to a particular receiver. Unfortunately, there's nothing I could find in the standard or Boost that does that.
What you can do is write your own fairly easily.
template <typename R, typename T>
struct member_function_binder {
T *receiver;
R T::*pmf;
template <typename... Args>
auto operator()(Args&&... args) {
return (receiver->*pmf)(std::forward<Args>(args)...);
}
};
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return member_function_binder<R, T>{&receiver, pmf};
}
Have a look at the live demo, I think this might be what you want.
Even more concise, you don't need to have a separate class member_function_binder
if you return a lambda from bind_member_function
like so:
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return [pmf, &receiver](auto&&... args) {
return (receiver.*pmf)(std::forward<decltype(args)>(args)...);
};
}
Live demo
Solution to pass a unary member function like Foo::compareTo(const Foo &rhs)
, not what OP asked:
What you want is std::mem_fn
; it's a wrapper that makes a member function pointer into a function object. You would use it like this:
auto min = std::min_element(
begin(mySet), end(mySet), std::mem_fn(&Foo::myWeakLessOperator));
myWeakLessOperator
is a 2-parameter member function
– Piotr Skotnicki
Nov 15 '18 at 17:55
@PiotrSkotnicki I just noticed that too, that doesn't seem very sensible though.
– Pezo
Nov 15 '18 at 17:56
I don't think this would work, as you need 3 parameters to invoke the wrapper properly in this example.
– user1095108
Nov 15 '18 at 17:56
add a comment |
So you want to have a function object that represents a member function bound to a particular receiver. Unfortunately, there's nothing I could find in the standard or Boost that does that.
What you can do is write your own fairly easily.
template <typename R, typename T>
struct member_function_binder {
T *receiver;
R T::*pmf;
template <typename... Args>
auto operator()(Args&&... args) {
return (receiver->*pmf)(std::forward<Args>(args)...);
}
};
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return member_function_binder<R, T>{&receiver, pmf};
}
Have a look at the live demo, I think this might be what you want.
Even more concise, you don't need to have a separate class member_function_binder
if you return a lambda from bind_member_function
like so:
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return [pmf, &receiver](auto&&... args) {
return (receiver.*pmf)(std::forward<decltype(args)>(args)...);
};
}
Live demo
Solution to pass a unary member function like Foo::compareTo(const Foo &rhs)
, not what OP asked:
What you want is std::mem_fn
; it's a wrapper that makes a member function pointer into a function object. You would use it like this:
auto min = std::min_element(
begin(mySet), end(mySet), std::mem_fn(&Foo::myWeakLessOperator));
So you want to have a function object that represents a member function bound to a particular receiver. Unfortunately, there's nothing I could find in the standard or Boost that does that.
What you can do is write your own fairly easily.
template <typename R, typename T>
struct member_function_binder {
T *receiver;
R T::*pmf;
template <typename... Args>
auto operator()(Args&&... args) {
return (receiver->*pmf)(std::forward<Args>(args)...);
}
};
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return member_function_binder<R, T>{&receiver, pmf};
}
Have a look at the live demo, I think this might be what you want.
Even more concise, you don't need to have a separate class member_function_binder
if you return a lambda from bind_member_function
like so:
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return [pmf, &receiver](auto&&... args) {
return (receiver.*pmf)(std::forward<decltype(args)>(args)...);
};
}
Live demo
Solution to pass a unary member function like Foo::compareTo(const Foo &rhs)
, not what OP asked:
What you want is std::mem_fn
; it's a wrapper that makes a member function pointer into a function object. You would use it like this:
auto min = std::min_element(
begin(mySet), end(mySet), std::mem_fn(&Foo::myWeakLessOperator));
edited Nov 16 '18 at 11:03
answered Nov 15 '18 at 17:52
PezoPezo
970512
970512
myWeakLessOperator
is a 2-parameter member function
– Piotr Skotnicki
Nov 15 '18 at 17:55
@PiotrSkotnicki I just noticed that too, that doesn't seem very sensible though.
– Pezo
Nov 15 '18 at 17:56
I don't think this would work, as you need 3 parameters to invoke the wrapper properly in this example.
– user1095108
Nov 15 '18 at 17:56
add a comment |
myWeakLessOperator
is a 2-parameter member function
– Piotr Skotnicki
Nov 15 '18 at 17:55
@PiotrSkotnicki I just noticed that too, that doesn't seem very sensible though.
– Pezo
Nov 15 '18 at 17:56
I don't think this would work, as you need 3 parameters to invoke the wrapper properly in this example.
– user1095108
Nov 15 '18 at 17:56
myWeakLessOperator
is a 2-parameter member function– Piotr Skotnicki
Nov 15 '18 at 17:55
myWeakLessOperator
is a 2-parameter member function– Piotr Skotnicki
Nov 15 '18 at 17:55
@PiotrSkotnicki I just noticed that too, that doesn't seem very sensible though.
– Pezo
Nov 15 '18 at 17:56
@PiotrSkotnicki I just noticed that too, that doesn't seem very sensible though.
– Pezo
Nov 15 '18 at 17:56
I don't think this would work, as you need 3 parameters to invoke the wrapper properly in this example.
– user1095108
Nov 15 '18 at 17:56
I don't think this would work, as you need 3 parameters to invoke the wrapper properly in this example.
– user1095108
Nov 15 '18 at 17:56
add a comment |
you can use std::bind
, or some other wrapper.
EXAMPLE:
using namespace std::placeholders;
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
std::bind(&Foo::myWeakLessOperator, bar, _1, _2));
OR
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
gnr::memfun<MEMFUN(Foo::myWeakLessOperator)>(bar));
Can you give an example, I am not used tostd::bind
and co, I cannot see how to use it.
– Azias
Nov 15 '18 at 18:30
Lambda is superior to everything, though, faster, takes up less space, ...
– user1095108
Nov 15 '18 at 18:53
I have tried with this example and it effectively does the job. thanks.
– Azias
Nov 16 '18 at 8:01
You should know thatstd::bind
is a lambda precursor. Effectively, the lambda replaces it and is superior.
– user1095108
Nov 16 '18 at 12:24
add a comment |
you can use std::bind
, or some other wrapper.
EXAMPLE:
using namespace std::placeholders;
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
std::bind(&Foo::myWeakLessOperator, bar, _1, _2));
OR
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
gnr::memfun<MEMFUN(Foo::myWeakLessOperator)>(bar));
Can you give an example, I am not used tostd::bind
and co, I cannot see how to use it.
– Azias
Nov 15 '18 at 18:30
Lambda is superior to everything, though, faster, takes up less space, ...
– user1095108
Nov 15 '18 at 18:53
I have tried with this example and it effectively does the job. thanks.
– Azias
Nov 16 '18 at 8:01
You should know thatstd::bind
is a lambda precursor. Effectively, the lambda replaces it and is superior.
– user1095108
Nov 16 '18 at 12:24
add a comment |
you can use std::bind
, or some other wrapper.
EXAMPLE:
using namespace std::placeholders;
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
std::bind(&Foo::myWeakLessOperator, bar, _1, _2));
OR
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
gnr::memfun<MEMFUN(Foo::myWeakLessOperator)>(bar));
you can use std::bind
, or some other wrapper.
EXAMPLE:
using namespace std::placeholders;
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
std::bind(&Foo::myWeakLessOperator, bar, _1, _2));
OR
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
gnr::memfun<MEMFUN(Foo::myWeakLessOperator)>(bar));
edited Nov 16 '18 at 12:28
answered Nov 15 '18 at 17:56
user1095108user1095108
7,12133380
7,12133380
Can you give an example, I am not used tostd::bind
and co, I cannot see how to use it.
– Azias
Nov 15 '18 at 18:30
Lambda is superior to everything, though, faster, takes up less space, ...
– user1095108
Nov 15 '18 at 18:53
I have tried with this example and it effectively does the job. thanks.
– Azias
Nov 16 '18 at 8:01
You should know thatstd::bind
is a lambda precursor. Effectively, the lambda replaces it and is superior.
– user1095108
Nov 16 '18 at 12:24
add a comment |
Can you give an example, I am not used tostd::bind
and co, I cannot see how to use it.
– Azias
Nov 15 '18 at 18:30
Lambda is superior to everything, though, faster, takes up less space, ...
– user1095108
Nov 15 '18 at 18:53
I have tried with this example and it effectively does the job. thanks.
– Azias
Nov 16 '18 at 8:01
You should know thatstd::bind
is a lambda precursor. Effectively, the lambda replaces it and is superior.
– user1095108
Nov 16 '18 at 12:24
Can you give an example, I am not used to
std::bind
and co, I cannot see how to use it.– Azias
Nov 15 '18 at 18:30
Can you give an example, I am not used to
std::bind
and co, I cannot see how to use it.– Azias
Nov 15 '18 at 18:30
Lambda is superior to everything, though, faster, takes up less space, ...
– user1095108
Nov 15 '18 at 18:53
Lambda is superior to everything, though, faster, takes up less space, ...
– user1095108
Nov 15 '18 at 18:53
I have tried with this example and it effectively does the job. thanks.
– Azias
Nov 16 '18 at 8:01
I have tried with this example and it effectively does the job. thanks.
– Azias
Nov 16 '18 at 8:01
You should know that
std::bind
is a lambda precursor. Effectively, the lambda replaces it and is superior.– user1095108
Nov 16 '18 at 12:24
You should know that
std::bind
is a lambda precursor. Effectively, the lambda replaces it and is superior.– user1095108
Nov 16 '18 at 12:24
add a comment |
The closest to what you want is maybe
auto minElement =
std::min_element(
std::begin(mySet),
std::end(mySet),
mem_fun_functor(&Foo::myWeakLessOperator)
);
There is std::mem_fun
(deprecated in c++11) and std::mem_fn
both wrap a member function pointer, though both take a instance as parameter to invoke the member function. If you want a functor that wraps the object also, i think you need to write your own:
auto mem_fun_functor =
[&bar](decltype(&Foo::myWeakLessOperator) f){
return [f,&bar](const Foo& a,const Foo& b) {
return (bar.*f)(a,b);
};
};
However, given that none of the answers is really much shorter or leading to cleaner code, I would consider to just use your first version with the lambda (unless you maybe have many different member functions that you want to use as comparator).
What do you actually mean by "simplifying" ? You do need to specify the object you want to call the member function on, you need to specify how you want to forward the parameters. Thats basically all the lambda does.
Defering all this to a functor as for example above makes your code more complicated rather than simpler. In your first snippet anybody familiar with standard algorithms can look at that few lines of code and fully understand what is going on.
Eventually it is a matter of style, and what you consider as readable, but being able to declare stuff in the most narrowest scope is one big advantage of using lambdas.
Correction:std::mem_fun
was deprecated long ago and removed in C++17, you shouldn't use that.std::mem_fn
is the way to go, it takes both references and pointers (raw or smart) as receivers.
– Pezo
Nov 15 '18 at 20:51
@Pezo thanks, corrected
– user463035818
Nov 15 '18 at 20:54
I really like your idea of returning a lambda, I never think of that.
– Pezo
Nov 15 '18 at 20:56
@Pezo my favourite is mjdmochowski's answer, though I really think just writing the lambda directly in the algorithm call is the most clean way. Its a bit of typing, but I prever to have everything in the most narrow scope. Whether there are reasons to pull something to a higher scope isnt really clear from the question
– user463035818
Nov 15 '18 at 21:00
I don't particularly like that solution since it'll waste space, because you need a reference/pointer to the containing object in the operator object (so it can access members).
– Pezo
Nov 16 '18 at 11:05
add a comment |
The closest to what you want is maybe
auto minElement =
std::min_element(
std::begin(mySet),
std::end(mySet),
mem_fun_functor(&Foo::myWeakLessOperator)
);
There is std::mem_fun
(deprecated in c++11) and std::mem_fn
both wrap a member function pointer, though both take a instance as parameter to invoke the member function. If you want a functor that wraps the object also, i think you need to write your own:
auto mem_fun_functor =
[&bar](decltype(&Foo::myWeakLessOperator) f){
return [f,&bar](const Foo& a,const Foo& b) {
return (bar.*f)(a,b);
};
};
However, given that none of the answers is really much shorter or leading to cleaner code, I would consider to just use your first version with the lambda (unless you maybe have many different member functions that you want to use as comparator).
What do you actually mean by "simplifying" ? You do need to specify the object you want to call the member function on, you need to specify how you want to forward the parameters. Thats basically all the lambda does.
Defering all this to a functor as for example above makes your code more complicated rather than simpler. In your first snippet anybody familiar with standard algorithms can look at that few lines of code and fully understand what is going on.
Eventually it is a matter of style, and what you consider as readable, but being able to declare stuff in the most narrowest scope is one big advantage of using lambdas.
Correction:std::mem_fun
was deprecated long ago and removed in C++17, you shouldn't use that.std::mem_fn
is the way to go, it takes both references and pointers (raw or smart) as receivers.
– Pezo
Nov 15 '18 at 20:51
@Pezo thanks, corrected
– user463035818
Nov 15 '18 at 20:54
I really like your idea of returning a lambda, I never think of that.
– Pezo
Nov 15 '18 at 20:56
@Pezo my favourite is mjdmochowski's answer, though I really think just writing the lambda directly in the algorithm call is the most clean way. Its a bit of typing, but I prever to have everything in the most narrow scope. Whether there are reasons to pull something to a higher scope isnt really clear from the question
– user463035818
Nov 15 '18 at 21:00
I don't particularly like that solution since it'll waste space, because you need a reference/pointer to the containing object in the operator object (so it can access members).
– Pezo
Nov 16 '18 at 11:05
add a comment |
The closest to what you want is maybe
auto minElement =
std::min_element(
std::begin(mySet),
std::end(mySet),
mem_fun_functor(&Foo::myWeakLessOperator)
);
There is std::mem_fun
(deprecated in c++11) and std::mem_fn
both wrap a member function pointer, though both take a instance as parameter to invoke the member function. If you want a functor that wraps the object also, i think you need to write your own:
auto mem_fun_functor =
[&bar](decltype(&Foo::myWeakLessOperator) f){
return [f,&bar](const Foo& a,const Foo& b) {
return (bar.*f)(a,b);
};
};
However, given that none of the answers is really much shorter or leading to cleaner code, I would consider to just use your first version with the lambda (unless you maybe have many different member functions that you want to use as comparator).
What do you actually mean by "simplifying" ? You do need to specify the object you want to call the member function on, you need to specify how you want to forward the parameters. Thats basically all the lambda does.
Defering all this to a functor as for example above makes your code more complicated rather than simpler. In your first snippet anybody familiar with standard algorithms can look at that few lines of code and fully understand what is going on.
Eventually it is a matter of style, and what you consider as readable, but being able to declare stuff in the most narrowest scope is one big advantage of using lambdas.
The closest to what you want is maybe
auto minElement =
std::min_element(
std::begin(mySet),
std::end(mySet),
mem_fun_functor(&Foo::myWeakLessOperator)
);
There is std::mem_fun
(deprecated in c++11) and std::mem_fn
both wrap a member function pointer, though both take a instance as parameter to invoke the member function. If you want a functor that wraps the object also, i think you need to write your own:
auto mem_fun_functor =
[&bar](decltype(&Foo::myWeakLessOperator) f){
return [f,&bar](const Foo& a,const Foo& b) {
return (bar.*f)(a,b);
};
};
However, given that none of the answers is really much shorter or leading to cleaner code, I would consider to just use your first version with the lambda (unless you maybe have many different member functions that you want to use as comparator).
What do you actually mean by "simplifying" ? You do need to specify the object you want to call the member function on, you need to specify how you want to forward the parameters. Thats basically all the lambda does.
Defering all this to a functor as for example above makes your code more complicated rather than simpler. In your first snippet anybody familiar with standard algorithms can look at that few lines of code and fully understand what is going on.
Eventually it is a matter of style, and what you consider as readable, but being able to declare stuff in the most narrowest scope is one big advantage of using lambdas.
edited Nov 15 '18 at 21:07
answered Nov 15 '18 at 20:25
user463035818user463035818
17.9k42868
17.9k42868
Correction:std::mem_fun
was deprecated long ago and removed in C++17, you shouldn't use that.std::mem_fn
is the way to go, it takes both references and pointers (raw or smart) as receivers.
– Pezo
Nov 15 '18 at 20:51
@Pezo thanks, corrected
– user463035818
Nov 15 '18 at 20:54
I really like your idea of returning a lambda, I never think of that.
– Pezo
Nov 15 '18 at 20:56
@Pezo my favourite is mjdmochowski's answer, though I really think just writing the lambda directly in the algorithm call is the most clean way. Its a bit of typing, but I prever to have everything in the most narrow scope. Whether there are reasons to pull something to a higher scope isnt really clear from the question
– user463035818
Nov 15 '18 at 21:00
I don't particularly like that solution since it'll waste space, because you need a reference/pointer to the containing object in the operator object (so it can access members).
– Pezo
Nov 16 '18 at 11:05
add a comment |
Correction:std::mem_fun
was deprecated long ago and removed in C++17, you shouldn't use that.std::mem_fn
is the way to go, it takes both references and pointers (raw or smart) as receivers.
– Pezo
Nov 15 '18 at 20:51
@Pezo thanks, corrected
– user463035818
Nov 15 '18 at 20:54
I really like your idea of returning a lambda, I never think of that.
– Pezo
Nov 15 '18 at 20:56
@Pezo my favourite is mjdmochowski's answer, though I really think just writing the lambda directly in the algorithm call is the most clean way. Its a bit of typing, but I prever to have everything in the most narrow scope. Whether there are reasons to pull something to a higher scope isnt really clear from the question
– user463035818
Nov 15 '18 at 21:00
I don't particularly like that solution since it'll waste space, because you need a reference/pointer to the containing object in the operator object (so it can access members).
– Pezo
Nov 16 '18 at 11:05
Correction:
std::mem_fun
was deprecated long ago and removed in C++17, you shouldn't use that. std::mem_fn
is the way to go, it takes both references and pointers (raw or smart) as receivers.– Pezo
Nov 15 '18 at 20:51
Correction:
std::mem_fun
was deprecated long ago and removed in C++17, you shouldn't use that. std::mem_fn
is the way to go, it takes both references and pointers (raw or smart) as receivers.– Pezo
Nov 15 '18 at 20:51
@Pezo thanks, corrected
– user463035818
Nov 15 '18 at 20:54
@Pezo thanks, corrected
– user463035818
Nov 15 '18 at 20:54
I really like your idea of returning a lambda, I never think of that.
– Pezo
Nov 15 '18 at 20:56
I really like your idea of returning a lambda, I never think of that.
– Pezo
Nov 15 '18 at 20:56
@Pezo my favourite is mjdmochowski's answer, though I really think just writing the lambda directly in the algorithm call is the most clean way. Its a bit of typing, but I prever to have everything in the most narrow scope. Whether there are reasons to pull something to a higher scope isnt really clear from the question
– user463035818
Nov 15 '18 at 21:00
@Pezo my favourite is mjdmochowski's answer, though I really think just writing the lambda directly in the algorithm call is the most clean way. Its a bit of typing, but I prever to have everything in the most narrow scope. Whether there are reasons to pull something to a higher scope isnt really clear from the question
– user463035818
Nov 15 '18 at 21:00
I don't particularly like that solution since it'll waste space, because you need a reference/pointer to the containing object in the operator object (so it can access members).
– Pezo
Nov 16 '18 at 11:05
I don't particularly like that solution since it'll waste space, because you need a reference/pointer to the containing object in the operator object (so it can access members).
– Pezo
Nov 16 '18 at 11:05
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%2f53325193%2fpass-a-member-function-as-compare-operator-for-c-standard-library-algorithm%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
with
std::bind(&Foo::myWeakLessOperator, std::placeholders::_1, std::placeholders::_1, std::placeholders::_2)
you can get away withbar
, but why not just make a static version ?– Piotr Skotnicki
Nov 15 '18 at 17:56
@PiotrSkotnicki in that case OP may just remove the first parameter from
myWeakLessOperator
altogether since it's justthis
duplicated.– Pezo
Nov 15 '18 at 17:58
1
@Azias could you elaborate on what
myWeakLessOperator
does, why is it a member function when it seems to compare two unrelated objects?– Pezo
Nov 15 '18 at 18:00
I cannot have a static version because the result of myWeakLessOperator will depend on the object. Actually my operator compares two objects against their distance to a main object (
myWeakLessOperator
could be renamedClosestThan
).bar
is the main object, and my final goal with std::min_element is to find the element frommySet' that is the closest to
bar`– Azias
Nov 15 '18 at 18:15
Then my answer is not a solution unfortunately, what you want is basically a bound member function. I had a need for this a couple days ago, but couldn't find anything, so I wrote my own. I'm trying to recreate it just now.
– Pezo
Nov 15 '18 at 18:21