-
-
Save dirvine/5921152 to your computer and use it in GitHub Desktop.
#ifndef MY_CLASS_H | |
#define MY_CLASS_H | |
#include <tuple> | |
#include <utility> | |
template <typename T, typename U> | |
struct MyClass { | |
T first; | |
U second; | |
// semiregular | |
MyClass(const MyClass& other) | |
: first(other.first), | |
second(other.second) | |
{} | |
MyClass(MyClass&& other) | |
: MyClass() { | |
swap(*this, other); | |
} | |
MyClass() | |
: first(), | |
second() | |
{} | |
~MyClass() | |
{} | |
MyClass& operator=(MyClass other) { | |
swap(*this, other); | |
return *this; | |
} | |
// regular | |
friend | |
bool operator==(const MyClass& lhs, const MyClass& rhs) { | |
return std::tie(lhs.first, lhs.second) | |
== std::tie(rhs.first, rhs.second); | |
} | |
friend | |
bool operator!=(const MyClass& lhs, const MyClass& rhs) { | |
return !operator==(lhs, rhs); | |
} | |
// fully ordered | |
friend | |
bool operator<(const MyClass& lhs, const MyClass& rhs) { | |
return std::tie(lhs.first, lhs.second) | |
< std::tie(rhs.first, rhs.second); | |
} | |
friend | |
bool operator>(const MyClass& lhs, const MyClass& rhs) { | |
return operator<(rhs, lhs); | |
} | |
friend | |
bool operator<=(const MyClass& lhs, const MyClass& rhs) { | |
return !operator>(lhs, rhs); | |
} | |
friend | |
bool operator>=(const MyClass& lhs, const MyClass& rhs) { | |
return !operator<(lhs, rhs); | |
} | |
}; | |
// swap | |
void swap(MyClass& lhs, MyClass& rhs) /* noexcept */ { | |
using std::swap; | |
swap(lhs.first, rhs.first); | |
swap(lhs.second, rhs.second); | |
} | |
#endif // MY_CLASS_H |
Oh and you're missing hash. Everyone always forgets hash, me as well.
Yes hash is important now and will be added. Good catch Niall. The linked presentation is very good. So here goes an hours study again :-) 👍
I am not sure, but perhaps best to keep swap as a friend of the class defined in the class ? I need to check but friend has altered in c++11 to be more of a route along ADL as opposed to a coupling mechanism. I prefer to have all the typical class members/features defined in place, I know Fraser prefers the opposite.
We would probably all prefer msvc played nice and we could just use = default = delete as well as ignore swap definitions like this at all as you say Niall.
In any case I think hash need to be a non member and specialisation of std::hash? is that right?
There is a standard definition of a standard type in c++. Read https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/cxx11-library-design.pdf?raw=true around page 35 onwards. Note the useful concept check test for a CI or static analyser to automate for you. As a summary, you need more noexcept and no swap which is now usually redundant.