#include #include using namespace std; #include // litte handy macro to access a column in the current object [ identic to FIELD(*this, Column) ] #define MYFIELD(Column) field((Column*)0) // encapsulation of comparision functions for table columns template struct Comparator { static bool is_less(const T& a, const T& b) {return FIELD(a,Column) < FIELD(b,Column);} }; template struct ComparisonFunctions { typedef bool (*CmpFct)(const T& a, const T& b); CmpFct _fcts[rel::list_length::result]; ComparisonFunctions() { // automatic initialisation of the arrays of comparison function pointers init_cmp_fcts(_fcts, (typename T::field_list*)0); } private: template static void init_cmp_fcts(CmpFct* pCmpFct, FieldList* = 0) { typedef FieldList::head Column; *pCmpFct = &Comparator::is_less; init_cmp_fcts(pCmpFct+1, (typename FieldList::tail*)0); } template<> static void init_cmp_fcts(CmpFct* pCmpFct, rel::null_type*) { } }; // sort policy using ComparisonFunctions to implement sorting on arbitrary columns using the column number template class column_sort { protected: typedef std::vector data; ComparisonFunctions::CmpFct _cur_cmp_fct; column_sort() : _current_sort_column(-1), _cur_cmp_fct(NULL) {} public: void sort(int sort_column) { const static ComparisonFunctions s_cmp_fcts; if (_current_sort_column == sort_column) return; _cur_cmp_fct = s_cmp_fcts._fcts[sort_column]; std::sort(m_data.begin(), m_data.end(), _cur_cmp_fct); _current_sort_column = sort_column; } void insert(const T& t) { m_data.push_back(t); _current_sort_column = -1; } private: int _current_sort_column; protected: data m_data; }; // usage example for class column_sort inline int quad(int x) { return x*x; } inline int digit_sum(int x) { int res = 0; while(x > 0) { res += x % 10; x /= 10; } return res>=10? digit_sum(res): res; } template int x_2_func(const T& t) { return quad(FIELD(t, x)); } template int x_digit_sum_func(const T& t) { return digit_sum(FIELD(t, x)); } template int x_2_digit_sum_func(const T& t) { return digit_sum(quad(FIELD(t, x))); } COLUMN (x, int) COLUMN (textual, std::string) CALCULATED_COLUMN (x_digit_sum, int, x_digit_sum_func); CALCULATED_COLUMN (x_2, int, x_2_func); CALCULATED_COLUMN (x_2_digit_sum, int, x_2_digit_sum_func); struct RowType : public rel::tuple< rel::list > > > > > { RowType(int n, const std::string& s) { MYFIELD(x) = n; MYFIELD(textual) = s; } RowType(const RowType& other) { MYFIELD(x) = FIELD(other, x); MYFIELD(textual) = FIELD(other, textual); } friend ostream& operator<<(ostream& out, const RowType& row) { out << FIELD(row, x) << '\t' << FIELD(row, textual) << '\t' << FIELD(row, x_digit_sum) << '\t' << FIELD(row, x_2) << '\t' << FIELD(row, x_2_digit_sum) << '\n'; return out; } }; typedef rel::table > TestTable; int main(int argc, char* argv[]) { TestTable table; table.insert(RowType(12, "twelve")); table.insert(RowType(11, "eleven")); table.insert(RowType(10, "ten")); table.insert(RowType( 9, "nine")); table.insert(RowType( 8, "eight")); table.insert(RowType( 7, "seven")); table.insert(RowType( 6, "six")); table.insert(RowType( 5, "five")); table.insert(RowType( 4, "four")); table.insert(RowType( 3, "three")); table.insert(RowType( 2, "two")); table.insert(RowType( 1, "one")); cout << "initial table content:\n"; copy(table.begin(), table.end(), ostream_iterator(cout)); cout << '\n'; for(int sort_column=0; sort_column::result; ++sort_column) { switch(sort_column) { case 0: cout << "sorting for column 0, the number in field x:\n"; break; case 1: cout << "sorting for column 1, the textual representation of the numbers:\n"; break; case 2: cout << "sorting for column with index 2, the calculated column x_digit_sum:\n"; break; default: cout << "sorting for column " << sort_column << ":\n"; } table.sort(sort_column); copy(table.begin(), table.end(), ostream_iterator(cout)); cout << '\n'; } return EXIT_SUCCESS; }