Efficient and simple comparison operators for structs

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
14
down vote

favorite
2












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:



  1. These expressions get huge if the structs as a dozen or more members.

  2. It is cumbersome to write and maintain if members change.

  3. It needs to be done for every struct separately.

Is there a more maintainable way to compare structs like this?










share|improve this question

















  • 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 tuples over structs, 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














up vote
14
down vote

favorite
2












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:



  1. These expressions get huge if the structs as a dozen or more members.

  2. It is cumbersome to write and maintain if members change.

  3. It needs to be done for every struct separately.

Is there a more maintainable way to compare structs like this?










share|improve this question

















  • 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 tuples over structs, 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












up vote
14
down vote

favorite
2









up vote
14
down vote

favorite
2






2





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:



  1. These expressions get huge if the structs as a dozen or more members.

  2. It is cumbersome to write and maintain if members change.

  3. It needs to be done for every struct separately.

Is there a more maintainable way to compare structs like this?










share|improve this question













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:



  1. These expressions get huge if the structs as a dozen or more members.

  2. It is cumbersome to write and maintain if members change.

  3. It needs to be done for every struct separately.

Is there a more maintainable way to compare structs like this?







c++






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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 using tuples over structs, 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




    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 tuples over structs, 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 tuples over structs, it includes a comparison operator with that meaning.
– papagaga
Sep 5 at 9:14




Consider using tuples over structs, 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












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




  1. 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 < and operator == for you.



  2. 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).


  3. If there is no intrinsic ordering related to A and you just need operator < to store instances as keys in a std::map, consider providing a named predicate.






share|improve this answer


















  • 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


















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






share|improve this answer






















  • 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




    @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










  • @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










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',
convertImagesToLinks: true,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52180053%2fefficient-and-simple-comparison-operators-for-structs%23new-answer', 'question_page');

);

Post as a guest






























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




  1. 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 < and operator == for you.



  2. 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).


  3. If there is no intrinsic ordering related to A and you just need operator < to store instances as keys in a std::map, consider providing a named predicate.






share|improve this answer


















  • 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















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




  1. 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 < and operator == for you.



  2. 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).


  3. If there is no intrinsic ordering related to A and you just need operator < to store instances as keys in a std::map, consider providing a named predicate.






share|improve this answer


















  • 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













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




  1. 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 < and operator == for you.



  2. 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).


  3. If there is no intrinsic ordering related to A and you just need operator < to store instances as keys in a std::map, consider providing a named predicate.






share|improve this answer














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




  1. 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 < and operator == for you.



  2. 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).


  3. If there is no intrinsic ordering related to A and you just need operator < to store instances as keys in a std::map, consider providing a named predicate.







share|improve this answer














share|improve this answer



share|improve this answer








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 boon auto operator<=>(const A&) = default; is going to be.
    – StoryTeller
    Sep 5 at 8:13













  • 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








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













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






share|improve this answer






















  • 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




    @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










  • @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














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






share|improve this answer






















  • 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




    @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










  • @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












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






share|improve this answer














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







share|improve this answer














share|improve this answer



share|improve this answer








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 that decltype? Is their purpose to SFINAE (and if so, what does the void() 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 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
















  • 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




    @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










  • @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

















 

draft saved


draft discarded















































 


draft saved


draft discarded














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













































































這個網誌中的熱門文章

How to combine Bézier curves to a surface?

Carbon dioxide

Why am i infinitely getting the same tweet with the Twitter Search API?