Efficient and simple comparison operators for structs
Clash Royale CLAN TAG#URR8PPP
up vote
14
down vote
favorite
The application I am working on currently has a large number structs which contain data which is input from various sources such as data bases and files. For example like this:
struct A
float val1;
std::string val2;
int val3;
bool operator < (const A& other) const;
;
For processing, these structs are stored up in STL-containers, such as maps and therefore need a comparison operator. These are all the same and using simple boolean logic they can be written like this:
bool A:operator < (const A& o) const
(val2 == o.val2 && ( val3 < o.val3 ) ) );
This seems efficient, but has several drawbacks:
- These expressions get huge if the structs as a dozen or more members.
- It is cumbersome to write and maintain if members change.
- It needs to be done for every struct separately.
Is there a more maintainable way to compare structs like this?
c++
add a comment |Â
up vote
14
down vote
favorite
The application I am working on currently has a large number structs which contain data which is input from various sources such as data bases and files. For example like this:
struct A
float val1;
std::string val2;
int val3;
bool operator < (const A& other) const;
;
For processing, these structs are stored up in STL-containers, such as maps and therefore need a comparison operator. These are all the same and using simple boolean logic they can be written like this:
bool A:operator < (const A& o) const
(val2 == o.val2 && ( val3 < o.val3 ) ) );
This seems efficient, but has several drawbacks:
- These expressions get huge if the structs as a dozen or more members.
- It is cumbersome to write and maintain if members change.
- It needs to be done for every struct separately.
Is there a more maintainable way to compare structs like this?
c++
2
This is a very use-case dependent scenario. Not all structures need to compare all members in their comparison operator. And not all structures needs to have comparison operators (just storing in a vector, for example, doesn't need any comparison).
â Some programmer dude
Sep 5 at 8:02
It's not best practise to make operator< a member function, it should be a free function. This ensures that C++ applies the same type conversion rules to both sides of an expression using<
.
â john
Sep 5 at 8:31
Consider usingtuple
s overstruct
s, it includes a comparison operator with that meaning.
â papagaga
Sep 5 at 9:14
(There are no structs in C++,struct
declares a class)
â pipe
Sep 5 at 13:51
add a comment |Â
up vote
14
down vote
favorite
up vote
14
down vote
favorite
The application I am working on currently has a large number structs which contain data which is input from various sources such as data bases and files. For example like this:
struct A
float val1;
std::string val2;
int val3;
bool operator < (const A& other) const;
;
For processing, these structs are stored up in STL-containers, such as maps and therefore need a comparison operator. These are all the same and using simple boolean logic they can be written like this:
bool A:operator < (const A& o) const
(val2 == o.val2 && ( val3 < o.val3 ) ) );
This seems efficient, but has several drawbacks:
- These expressions get huge if the structs as a dozen or more members.
- It is cumbersome to write and maintain if members change.
- It needs to be done for every struct separately.
Is there a more maintainable way to compare structs like this?
c++
The application I am working on currently has a large number structs which contain data which is input from various sources such as data bases and files. For example like this:
struct A
float val1;
std::string val2;
int val3;
bool operator < (const A& other) const;
;
For processing, these structs are stored up in STL-containers, such as maps and therefore need a comparison operator. These are all the same and using simple boolean logic they can be written like this:
bool A:operator < (const A& o) const
(val2 == o.val2 && ( val3 < o.val3 ) ) );
This seems efficient, but has several drawbacks:
- These expressions get huge if the structs as a dozen or more members.
- It is cumbersome to write and maintain if members change.
- It needs to be done for every struct separately.
Is there a more maintainable way to compare structs like this?
c++
c++
asked Sep 5 at 7:59
Beginner
2,55021746
2,55021746
2
This is a very use-case dependent scenario. Not all structures need to compare all members in their comparison operator. And not all structures needs to have comparison operators (just storing in a vector, for example, doesn't need any comparison).
â Some programmer dude
Sep 5 at 8:02
It's not best practise to make operator< a member function, it should be a free function. This ensures that C++ applies the same type conversion rules to both sides of an expression using<
.
â john
Sep 5 at 8:31
Consider usingtuple
s overstruct
s, it includes a comparison operator with that meaning.
â papagaga
Sep 5 at 9:14
(There are no structs in C++,struct
declares a class)
â pipe
Sep 5 at 13:51
add a comment |Â
2
This is a very use-case dependent scenario. Not all structures need to compare all members in their comparison operator. And not all structures needs to have comparison operators (just storing in a vector, for example, doesn't need any comparison).
â Some programmer dude
Sep 5 at 8:02
It's not best practise to make operator< a member function, it should be a free function. This ensures that C++ applies the same type conversion rules to both sides of an expression using<
.
â john
Sep 5 at 8:31
Consider usingtuple
s overstruct
s, it includes a comparison operator with that meaning.
â papagaga
Sep 5 at 9:14
(There are no structs in C++,struct
declares a class)
â pipe
Sep 5 at 13:51
2
2
This is a very use-case dependent scenario. Not all structures need to compare all members in their comparison operator. And not all structures needs to have comparison operators (just storing in a vector, for example, doesn't need any comparison).
â Some programmer dude
Sep 5 at 8:02
This is a very use-case dependent scenario. Not all structures need to compare all members in their comparison operator. And not all structures needs to have comparison operators (just storing in a vector, for example, doesn't need any comparison).
â Some programmer dude
Sep 5 at 8:02
It's not best practise to make operator< a member function, it should be a free function. This ensures that C++ applies the same type conversion rules to both sides of an expression using
<
.â john
Sep 5 at 8:31
It's not best practise to make operator< a member function, it should be a free function. This ensures that C++ applies the same type conversion rules to both sides of an expression using
<
.â john
Sep 5 at 8:31
Consider using
tuple
s over struct
s, it includes a comparison operator with that meaning.â papagaga
Sep 5 at 9:14
Consider using
tuple
s over struct
s, it includes a comparison operator with that meaning.â papagaga
Sep 5 at 9:14
(There are no structs in C++,
struct
declares a class)â pipe
Sep 5 at 13:51
(There are no structs in C++,
struct
declares a class)â pipe
Sep 5 at 13:51
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
20
down vote
accepted
You can use the builtin comparison that ships with <tuple>
like this:
#include <tuple>
bool A::operator < (const A& rhs) const
return std::tie(val1, val2, val3) < std::tie(rhs.val1, rhs.val2, rhs.val3);
This doesn't scale when more and more data members are added to the struct, but this might also be a hint that you could create intermediate structs that implement operator <
and hence play well with the above implementation of a top-level operator <
.
Let me add three additional comments on operator <
.
Once you have
operator <
, clients will expect that all other comparison operators are provided, too. Before we have the three-way comparison in C++20, you can avoid unnecessary boilerplate code by e.g. using the Boost operator library:#include <boost/operators.hpp>
struct A : private boost::totally_ordered<A> /* ... */ ;which generates all operators based on
operator <
andoperator ==
for you.In your example, there is no need for the operator to be a member of
A
. You can make it a free function, which is preferable (see here for the rationale).If there is no intrinsic ordering related to
A
and you just needoperator <
to store instances as keys in astd::map
, consider providing a named predicate.
8
All this boiler-plate really emphasizes how much of a boonauto operator<=>(const A&) = default;
is going to be.
â StoryTeller
Sep 5 at 8:13
add a comment |Â
up vote
8
down vote
Great answer by lubgr.
One further refinement I perform is the creation of a member function as_tuple
on any object which is to be ordered by its members:
#include <string>
#include <tuple>
#include <iostream>
struct A
float val1;
std::string val2;
int val3;
// provide easy conversion to tuple
auto as_tuple() const
return std::tie(val1, val2, val3);
;
Which often gives rise to thoughts of a general system of making objects and tuples interchangeable in terms of comparisons
template<class T> auto as_tuple(T&& l) -> decltype(l.as_tuple())
return l.as_tuple();
template<class...Ts>
auto as_tuple(std::tuple<Ts...> const& tup)
-> decltype(auto)
return tup;
template<class L, class R>
auto operator < (L const& l, R const& r)
-> decltype(as_tuple(l), void(), as_tuple(r), void(), bool())
return as_tuple(l) < as_tuple(r);
Which allows such code as:
int main()
auto a = A 1.1, "foo", 0 ;
auto b = A 1.1, "foo", 1 ;
auto test1 = a < b;
std::cout << test1 << std::endl;
auto test2 = a < std::make_tuple(1.1, "bar", 0);
std::cout << test2 << std::endl;
auto test3 = std::make_tuple(1.0, "bar", 0) < std::make_tuple(1.1, "bar", 0);
std::cout << test3 << std::endl;
auto test4 = a < std::make_tuple(2l, std::string("bar"), 0);
std::cout << test4 << std::endl;
example: http://coliru.stacked-crooked.com/a/ead750f3f65e3ee9
Am I understanding correctly that there are several comma operators in thatdecltype
? Is their purpose to SFINAE (and if so, what does thevoid()
accomplish)?
â Max Langhof
Sep 5 at 9:56
1
@MaxLanghof yes their purpose is SFINAE. The void() acts as a separator which eliminates a very unlikely corner case. Imagine if as_tuple(R) returned a type for which a comma (,) operator had been defined. This would change the meaning of the expression in the decltype.
â Richard Hodges
Sep 5 at 9:58
@RichardHodges - Isn't that a concern foras_tuple(l)
too?
â StoryTeller
Sep 5 at 16:33
@StoryTeller yes you're right. I had the same thought after the question was posed. I'll update it.
â Richard Hodges
Sep 5 at 19:40
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
20
down vote
accepted
You can use the builtin comparison that ships with <tuple>
like this:
#include <tuple>
bool A::operator < (const A& rhs) const
return std::tie(val1, val2, val3) < std::tie(rhs.val1, rhs.val2, rhs.val3);
This doesn't scale when more and more data members are added to the struct, but this might also be a hint that you could create intermediate structs that implement operator <
and hence play well with the above implementation of a top-level operator <
.
Let me add three additional comments on operator <
.
Once you have
operator <
, clients will expect that all other comparison operators are provided, too. Before we have the three-way comparison in C++20, you can avoid unnecessary boilerplate code by e.g. using the Boost operator library:#include <boost/operators.hpp>
struct A : private boost::totally_ordered<A> /* ... */ ;which generates all operators based on
operator <
andoperator ==
for you.In your example, there is no need for the operator to be a member of
A
. You can make it a free function, which is preferable (see here for the rationale).If there is no intrinsic ordering related to
A
and you just needoperator <
to store instances as keys in astd::map
, consider providing a named predicate.
8
All this boiler-plate really emphasizes how much of a boonauto operator<=>(const A&) = default;
is going to be.
â StoryTeller
Sep 5 at 8:13
add a comment |Â
up vote
20
down vote
accepted
You can use the builtin comparison that ships with <tuple>
like this:
#include <tuple>
bool A::operator < (const A& rhs) const
return std::tie(val1, val2, val3) < std::tie(rhs.val1, rhs.val2, rhs.val3);
This doesn't scale when more and more data members are added to the struct, but this might also be a hint that you could create intermediate structs that implement operator <
and hence play well with the above implementation of a top-level operator <
.
Let me add three additional comments on operator <
.
Once you have
operator <
, clients will expect that all other comparison operators are provided, too. Before we have the three-way comparison in C++20, you can avoid unnecessary boilerplate code by e.g. using the Boost operator library:#include <boost/operators.hpp>
struct A : private boost::totally_ordered<A> /* ... */ ;which generates all operators based on
operator <
andoperator ==
for you.In your example, there is no need for the operator to be a member of
A
. You can make it a free function, which is preferable (see here for the rationale).If there is no intrinsic ordering related to
A
and you just needoperator <
to store instances as keys in astd::map
, consider providing a named predicate.
8
All this boiler-plate really emphasizes how much of a boonauto operator<=>(const A&) = default;
is going to be.
â StoryTeller
Sep 5 at 8:13
add a comment |Â
up vote
20
down vote
accepted
up vote
20
down vote
accepted
You can use the builtin comparison that ships with <tuple>
like this:
#include <tuple>
bool A::operator < (const A& rhs) const
return std::tie(val1, val2, val3) < std::tie(rhs.val1, rhs.val2, rhs.val3);
This doesn't scale when more and more data members are added to the struct, but this might also be a hint that you could create intermediate structs that implement operator <
and hence play well with the above implementation of a top-level operator <
.
Let me add three additional comments on operator <
.
Once you have
operator <
, clients will expect that all other comparison operators are provided, too. Before we have the three-way comparison in C++20, you can avoid unnecessary boilerplate code by e.g. using the Boost operator library:#include <boost/operators.hpp>
struct A : private boost::totally_ordered<A> /* ... */ ;which generates all operators based on
operator <
andoperator ==
for you.In your example, there is no need for the operator to be a member of
A
. You can make it a free function, which is preferable (see here for the rationale).If there is no intrinsic ordering related to
A
and you just needoperator <
to store instances as keys in astd::map
, consider providing a named predicate.
You can use the builtin comparison that ships with <tuple>
like this:
#include <tuple>
bool A::operator < (const A& rhs) const
return std::tie(val1, val2, val3) < std::tie(rhs.val1, rhs.val2, rhs.val3);
This doesn't scale when more and more data members are added to the struct, but this might also be a hint that you could create intermediate structs that implement operator <
and hence play well with the above implementation of a top-level operator <
.
Let me add three additional comments on operator <
.
Once you have
operator <
, clients will expect that all other comparison operators are provided, too. Before we have the three-way comparison in C++20, you can avoid unnecessary boilerplate code by e.g. using the Boost operator library:#include <boost/operators.hpp>
struct A : private boost::totally_ordered<A> /* ... */ ;which generates all operators based on
operator <
andoperator ==
for you.In your example, there is no need for the operator to be a member of
A
. You can make it a free function, which is preferable (see here for the rationale).If there is no intrinsic ordering related to
A
and you just needoperator <
to store instances as keys in astd::map
, consider providing a named predicate.
edited Sep 5 at 8:14
answered Sep 5 at 8:04
lubgr
6,72521340
6,72521340
8
All this boiler-plate really emphasizes how much of a boonauto operator<=>(const A&) = default;
is going to be.
â StoryTeller
Sep 5 at 8:13
add a comment |Â
8
All this boiler-plate really emphasizes how much of a boonauto operator<=>(const A&) = default;
is going to be.
â StoryTeller
Sep 5 at 8:13
8
8
All this boiler-plate really emphasizes how much of a boon
auto operator<=>(const A&) = default;
is going to be.â StoryTeller
Sep 5 at 8:13
All this boiler-plate really emphasizes how much of a boon
auto operator<=>(const A&) = default;
is going to be.â StoryTeller
Sep 5 at 8:13
add a comment |Â
up vote
8
down vote
Great answer by lubgr.
One further refinement I perform is the creation of a member function as_tuple
on any object which is to be ordered by its members:
#include <string>
#include <tuple>
#include <iostream>
struct A
float val1;
std::string val2;
int val3;
// provide easy conversion to tuple
auto as_tuple() const
return std::tie(val1, val2, val3);
;
Which often gives rise to thoughts of a general system of making objects and tuples interchangeable in terms of comparisons
template<class T> auto as_tuple(T&& l) -> decltype(l.as_tuple())
return l.as_tuple();
template<class...Ts>
auto as_tuple(std::tuple<Ts...> const& tup)
-> decltype(auto)
return tup;
template<class L, class R>
auto operator < (L const& l, R const& r)
-> decltype(as_tuple(l), void(), as_tuple(r), void(), bool())
return as_tuple(l) < as_tuple(r);
Which allows such code as:
int main()
auto a = A 1.1, "foo", 0 ;
auto b = A 1.1, "foo", 1 ;
auto test1 = a < b;
std::cout << test1 << std::endl;
auto test2 = a < std::make_tuple(1.1, "bar", 0);
std::cout << test2 << std::endl;
auto test3 = std::make_tuple(1.0, "bar", 0) < std::make_tuple(1.1, "bar", 0);
std::cout << test3 << std::endl;
auto test4 = a < std::make_tuple(2l, std::string("bar"), 0);
std::cout << test4 << std::endl;
example: http://coliru.stacked-crooked.com/a/ead750f3f65e3ee9
Am I understanding correctly that there are several comma operators in thatdecltype
? Is their purpose to SFINAE (and if so, what does thevoid()
accomplish)?
â Max Langhof
Sep 5 at 9:56
1
@MaxLanghof yes their purpose is SFINAE. The void() acts as a separator which eliminates a very unlikely corner case. Imagine if as_tuple(R) returned a type for which a comma (,) operator had been defined. This would change the meaning of the expression in the decltype.
â Richard Hodges
Sep 5 at 9:58
@RichardHodges - Isn't that a concern foras_tuple(l)
too?
â StoryTeller
Sep 5 at 16:33
@StoryTeller yes you're right. I had the same thought after the question was posed. I'll update it.
â Richard Hodges
Sep 5 at 19:40
add a comment |Â
up vote
8
down vote
Great answer by lubgr.
One further refinement I perform is the creation of a member function as_tuple
on any object which is to be ordered by its members:
#include <string>
#include <tuple>
#include <iostream>
struct A
float val1;
std::string val2;
int val3;
// provide easy conversion to tuple
auto as_tuple() const
return std::tie(val1, val2, val3);
;
Which often gives rise to thoughts of a general system of making objects and tuples interchangeable in terms of comparisons
template<class T> auto as_tuple(T&& l) -> decltype(l.as_tuple())
return l.as_tuple();
template<class...Ts>
auto as_tuple(std::tuple<Ts...> const& tup)
-> decltype(auto)
return tup;
template<class L, class R>
auto operator < (L const& l, R const& r)
-> decltype(as_tuple(l), void(), as_tuple(r), void(), bool())
return as_tuple(l) < as_tuple(r);
Which allows such code as:
int main()
auto a = A 1.1, "foo", 0 ;
auto b = A 1.1, "foo", 1 ;
auto test1 = a < b;
std::cout << test1 << std::endl;
auto test2 = a < std::make_tuple(1.1, "bar", 0);
std::cout << test2 << std::endl;
auto test3 = std::make_tuple(1.0, "bar", 0) < std::make_tuple(1.1, "bar", 0);
std::cout << test3 << std::endl;
auto test4 = a < std::make_tuple(2l, std::string("bar"), 0);
std::cout << test4 << std::endl;
example: http://coliru.stacked-crooked.com/a/ead750f3f65e3ee9
Am I understanding correctly that there are several comma operators in thatdecltype
? Is their purpose to SFINAE (and if so, what does thevoid()
accomplish)?
â Max Langhof
Sep 5 at 9:56
1
@MaxLanghof yes their purpose is SFINAE. The void() acts as a separator which eliminates a very unlikely corner case. Imagine if as_tuple(R) returned a type for which a comma (,) operator had been defined. This would change the meaning of the expression in the decltype.
â Richard Hodges
Sep 5 at 9:58
@RichardHodges - Isn't that a concern foras_tuple(l)
too?
â StoryTeller
Sep 5 at 16:33
@StoryTeller yes you're right. I had the same thought after the question was posed. I'll update it.
â Richard Hodges
Sep 5 at 19:40
add a comment |Â
up vote
8
down vote
up vote
8
down vote
Great answer by lubgr.
One further refinement I perform is the creation of a member function as_tuple
on any object which is to be ordered by its members:
#include <string>
#include <tuple>
#include <iostream>
struct A
float val1;
std::string val2;
int val3;
// provide easy conversion to tuple
auto as_tuple() const
return std::tie(val1, val2, val3);
;
Which often gives rise to thoughts of a general system of making objects and tuples interchangeable in terms of comparisons
template<class T> auto as_tuple(T&& l) -> decltype(l.as_tuple())
return l.as_tuple();
template<class...Ts>
auto as_tuple(std::tuple<Ts...> const& tup)
-> decltype(auto)
return tup;
template<class L, class R>
auto operator < (L const& l, R const& r)
-> decltype(as_tuple(l), void(), as_tuple(r), void(), bool())
return as_tuple(l) < as_tuple(r);
Which allows such code as:
int main()
auto a = A 1.1, "foo", 0 ;
auto b = A 1.1, "foo", 1 ;
auto test1 = a < b;
std::cout << test1 << std::endl;
auto test2 = a < std::make_tuple(1.1, "bar", 0);
std::cout << test2 << std::endl;
auto test3 = std::make_tuple(1.0, "bar", 0) < std::make_tuple(1.1, "bar", 0);
std::cout << test3 << std::endl;
auto test4 = a < std::make_tuple(2l, std::string("bar"), 0);
std::cout << test4 << std::endl;
example: http://coliru.stacked-crooked.com/a/ead750f3f65e3ee9
Great answer by lubgr.
One further refinement I perform is the creation of a member function as_tuple
on any object which is to be ordered by its members:
#include <string>
#include <tuple>
#include <iostream>
struct A
float val1;
std::string val2;
int val3;
// provide easy conversion to tuple
auto as_tuple() const
return std::tie(val1, val2, val3);
;
Which often gives rise to thoughts of a general system of making objects and tuples interchangeable in terms of comparisons
template<class T> auto as_tuple(T&& l) -> decltype(l.as_tuple())
return l.as_tuple();
template<class...Ts>
auto as_tuple(std::tuple<Ts...> const& tup)
-> decltype(auto)
return tup;
template<class L, class R>
auto operator < (L const& l, R const& r)
-> decltype(as_tuple(l), void(), as_tuple(r), void(), bool())
return as_tuple(l) < as_tuple(r);
Which allows such code as:
int main()
auto a = A 1.1, "foo", 0 ;
auto b = A 1.1, "foo", 1 ;
auto test1 = a < b;
std::cout << test1 << std::endl;
auto test2 = a < std::make_tuple(1.1, "bar", 0);
std::cout << test2 << std::endl;
auto test3 = std::make_tuple(1.0, "bar", 0) < std::make_tuple(1.1, "bar", 0);
std::cout << test3 << std::endl;
auto test4 = a < std::make_tuple(2l, std::string("bar"), 0);
std::cout << test4 << std::endl;
example: http://coliru.stacked-crooked.com/a/ead750f3f65e3ee9
edited Sep 5 at 19:42
answered Sep 5 at 9:44
Richard Hodges
54k55698
54k55698
Am I understanding correctly that there are several comma operators in thatdecltype
? Is their purpose to SFINAE (and if so, what does thevoid()
accomplish)?
â Max Langhof
Sep 5 at 9:56
1
@MaxLanghof yes their purpose is SFINAE. The void() acts as a separator which eliminates a very unlikely corner case. Imagine if as_tuple(R) returned a type for which a comma (,) operator had been defined. This would change the meaning of the expression in the decltype.
â Richard Hodges
Sep 5 at 9:58
@RichardHodges - Isn't that a concern foras_tuple(l)
too?
â StoryTeller
Sep 5 at 16:33
@StoryTeller yes you're right. I had the same thought after the question was posed. I'll update it.
â Richard Hodges
Sep 5 at 19:40
add a comment |Â
Am I understanding correctly that there are several comma operators in thatdecltype
? Is their purpose to SFINAE (and if so, what does thevoid()
accomplish)?
â Max Langhof
Sep 5 at 9:56
1
@MaxLanghof yes their purpose is SFINAE. The void() acts as a separator which eliminates a very unlikely corner case. Imagine if as_tuple(R) returned a type for which a comma (,) operator had been defined. This would change the meaning of the expression in the decltype.
â Richard Hodges
Sep 5 at 9:58
@RichardHodges - Isn't that a concern foras_tuple(l)
too?
â StoryTeller
Sep 5 at 16:33
@StoryTeller yes you're right. I had the same thought after the question was posed. I'll update it.
â Richard Hodges
Sep 5 at 19:40
Am I understanding correctly that there are several comma operators in that
decltype
? Is their purpose to SFINAE (and if so, what does the void()
accomplish)?â Max Langhof
Sep 5 at 9:56
Am I understanding correctly that there are several comma operators in that
decltype
? Is their purpose to SFINAE (and if so, what does the void()
accomplish)?â Max Langhof
Sep 5 at 9:56
1
1
@MaxLanghof yes their purpose is SFINAE. The void() acts as a separator which eliminates a very unlikely corner case. Imagine if as_tuple(R) returned a type for which a comma (,) operator had been defined. This would change the meaning of the expression in the decltype.
â Richard Hodges
Sep 5 at 9:58
@MaxLanghof yes their purpose is SFINAE. The void() acts as a separator which eliminates a very unlikely corner case. Imagine if as_tuple(R) returned a type for which a comma (,) operator had been defined. This would change the meaning of the expression in the decltype.
â Richard Hodges
Sep 5 at 9:58
@RichardHodges - Isn't that a concern for
as_tuple(l)
too?â StoryTeller
Sep 5 at 16:33
@RichardHodges - Isn't that a concern for
as_tuple(l)
too?â StoryTeller
Sep 5 at 16:33
@StoryTeller yes you're right. I had the same thought after the question was posed. I'll update it.
â Richard Hodges
Sep 5 at 19:40
@StoryTeller yes you're right. I had the same thought after the question was posed. I'll update it.
â Richard Hodges
Sep 5 at 19:40
add a comment |Â
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
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52180053%2fefficient-and-simple-comparison-operators-for-structs%23new-answer', 'question_page');
);
Post as a guest
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
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
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
2
This is a very use-case dependent scenario. Not all structures need to compare all members in their comparison operator. And not all structures needs to have comparison operators (just storing in a vector, for example, doesn't need any comparison).
â Some programmer dude
Sep 5 at 8:02
It's not best practise to make operator< a member function, it should be a free function. This ensures that C++ applies the same type conversion rules to both sides of an expression using
<
.â john
Sep 5 at 8:31
Consider using
tuple
s overstruct
s, it includes a comparison operator with that meaning.â papagaga
Sep 5 at 9:14
(There are no structs in C++,
struct
declares a class)â pipe
Sep 5 at 13:51