Created
May 25, 2013 19:44
-
-
Save hacst/5650513 to your computer and use it in GitHub Desktop.
Experimentation with typesafe indices for https://plus.google.com/u/0/103771295878903986513/posts/CiwQXgwHbJ1
Basically the gist of what I wanted from a strongly typedef'd size_t. This example only implements the operators I needed and already took quite a bit of code that might (will ;) ) contain bugs and unexpected behavior. For my application…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <vector> | |
#include <cstddef> | |
template<typename Tag> | |
class TypesafeIndex | |
{ | |
public: | |
inline TypesafeIndex() : m_i() {}; | |
inline explicit TypesafeIndex(const size_t a_value) : m_i(a_value) {}; | |
inline TypesafeIndex<Tag>& operator=(TypesafeIndex<Tag> a_rhs) { m_i = a_rhs.m_i; return *this; }; | |
inline TypesafeIndex<Tag>& operator=(size_t a_rhs) { m_i = a_rhs; return *this; }; | |
inline bool operator==(const Tag a_rhs) const { return m_i == a_rhs; }; | |
inline bool operator==(const TypesafeIndex<Tag> a_rhs) const { return m_i == a_rhs; }; | |
inline bool operator<(const TypesafeIndex<Tag> a_rhs) const { return m_i < a_rhs.m_i; }; | |
inline bool operator<(const size_t a_rhs) const { return m_i < a_rhs; }; | |
inline bool operator<=(const TypesafeIndex<Tag> a_rhs) const { return m_i <= a_rhs.m_i; }; | |
inline bool operator<=(const size_t a_rhs) const { return m_i <= a_rhs; }; | |
inline TypesafeIndex<Tag>& operator++(int) { ++m_i; return *this; }; | |
inline TypesafeIndex<Tag> operator++() { TypesafeIndex<Tag> retval(m_i++); return retval; }; | |
inline TypesafeIndex<Tag>& operator--(int) { --m_i; return *this; }; | |
inline TypesafeIndex<Tag> operator--() { TypesafeIndex<Tag> retval(m_i--); return retval; }; | |
inline TypesafeIndex<Tag> operator-(const TypesafeIndex<Tag> a_rhs) const { return TypesafeIndex<Tag>(m_i - a_rhs.m_i); }; | |
inline TypesafeIndex<Tag> operator-(const size_t a_rhs) const { return TypesafeIndex<Tag>(m_i - a_rhs); }; | |
inline TypesafeIndex<Tag> operator-(const int a_rhs) const { return TypesafeIndex<Tag>(m_i - a_rhs); }; | |
inline TypesafeIndex<Tag> operator+(const TypesafeIndex<Tag> a_rhs) const { return TypesafeIndex<Tag>(m_i + a_rhs.m_i); }; | |
inline TypesafeIndex<Tag> operator+(const size_t a_rhs) const { return TypesafeIndex<Tag>(m_i + a_rhs); }; | |
inline TypesafeIndex<Tag> operator+(const int a_rhs) const { return TypesafeIndex<Tag>(m_i + a_rhs); }; | |
inline operator size_t () const { return m_i; }; | |
private: | |
size_t m_i; | |
}; | |
class Matrix { | |
class IndexXTypeTag {}; | |
class IndexYTypeTag {}; | |
public: | |
typedef TypesafeIndex<IndexXTypeTag> X; | |
typedef TypesafeIndex<IndexYTypeTag> Y; | |
Matrix(X a_endX, Y a_endY) | |
: m_endY(a_endX) | |
, m_matrix(a_endX * a_endY) { /* EMPTY */ } | |
int& operator()(X a, Y b) { | |
return m_matrix[a * m_endY + b]; // Implicit conversion to size_t if needed, but only if needed | |
}; | |
private: | |
Y m_endY; | |
std::vector<int> m_matrix; | |
}; | |
int main() { | |
typedef Matrix::X X; | |
typedef Matrix::Y Y; | |
X endX = X(10); // Explicit construction | |
Y endY = Y(20); | |
Matrix matrix(endX, endY); | |
matrix(X(1),Y(0)) = 1; | |
matrix(X(0),Y(1)) = 2; | |
for (X x(1); x < endX; ++x) // Usable as loop variable | |
{ | |
for (Y y(1); y < endY; ++y) | |
{ | |
matrix(x,y) = matrix(x-1,y) + matrix(x,y-1); // No additional syntax when doing normal index calculations | |
//matrix(y+2,x); // Will catch swapped paramters | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment