std::vector<T>)
a with an object of the same type b, e.g. T a(b); or T a = b (equivalent if a and b have the same type)a should be equivalent to b after copyingR(a,b) is equivalent if it is:
R(a,b) <=> R(b,a)R(a,a)if\ R(a,b)\ and\ R(b,c)=>R(a,c)a is copy constructed from original b, then a==b for however we define this equalityT a; a = b; -> the assignment operator is the =a to an object which is equal to bT a1(b) and T a2; a2 = b should always yield a1 == a2== operator to be defined for the objects; how else would you otherwise decide if two instances are equal??
== (and by extension !=) operator defined for them== is the required function of regular types== must be symmetricTotallyOrdered is defined which extends Regular by adding the comparison operator << must obey the properties:
a can never be < aa<b then b can never be < aa!=b then a<b or a>b< are bound to the sematics of equality and related operations; e.g. if a >= b then a cannot be < b<=> is a helper operator that returns <0 if a<b, >0 if a>b and returns 0 when a==b. We can define this one function and the compiler will auto generate all the other functions for us&) to get reference semantics similar to Javatemplate <typename T>
struct singleton
{
T value;
}
singleton<int> s;)singleton<int> s1 = ssingleton<int> s2; s2 = s1struct singleton {
T value;
singleton() {}
~singleton() {}
// copy constructor
singleton(singleton const& x)
: value(x.value) { // this syntax is member initialisation syntax, which reduces unnecessary copying
}
// copy assignment
singleton& operator=(singleton const& x) {
value = x.value;
return *this;
}
}
= default; for these function definitions to use the compiler generated functions (which would have the same semantics as above)friend bool operator==(singleton const& x, singleton const& y) {
return x.value == y.value
}
friend bool operator!=(singleton const& x, singleton const& y) {
return !(x==y)
}
x.equals(y)a is always ==ax==x -> false and x!=x -> falseoperator< and we can then trivially derive all other orderings from thistemplate <typename T>
requires(std::regular<T> || std::semiregular<T> || std::totally_ordered<T>)
struct singleton final {
//...
}
T we can use with singletonT, then C++ templates ensures that singleton<T> will only have a copy constructor and assignment, no equalityT will add regularity to singleton etc.T and behave exactly like a T but will allow us to count operations applied to itstd::set vs std::sort and std::unique for finding the number of unique elements in a collection; instrumented classes can be used to count the #operations taken in each case
std::vector is contiguous in memory meaning it is much friendlier on caches
std::vector as a container, this memory locality is critical to performance