/* * Copyright (c) 2009 Sebastian Nibisz * published under NCSA License * * member.hpp */ #ifndef MEMBER_HPP_INCLUDED #define MEMBER_HPP_INCLUDED #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif template class is_convertible { typedef char one; typedef struct { char c[2]; } two; static one test(U) ; static two test(...); static T makeT(); public: enum { yes = sizeof(test(makeT())) == sizeof(one) }; }; template struct object_traits { protected: template const T& reference(const U& o, V C::*k) const { return (*o).*k; } template T reference(const U& o, V (C::*k)() const) const { return ((*o).*k)(); } template const T& reference(const U& o, const V& (C::*k)() const) const { return ((*o).*k)(); } }; template struct object_traits { protected: template const T& reference(const U& o, V C::*k) const { return o.*k; } template T reference(const U& o, V (C::*k)() const) const { return (o.*k)(); } template const T& reference(const U& o, const V& (C::*k)() const) const { return (o.*k)(); } }; template struct field; template struct field { typedef const T& result_type; typedef T variable_type; typedef C object_type; }; template struct field { typedef T result_type; typedef T variable_type; typedef C object_type; }; template struct field { typedef const T& result_type; typedef T variable_type; typedef C object_type; }; template struct member : object_traits::variable_type, is_convertible::object_type>::yes> { typedef C value_type; typedef typename field::result_type result_key_type; typedef typename field::variable_type key_type; typedef typename field::object_type object_type; member(const value_type& o) : temporal_key(0) { new (buffer) value_type(o); } member(const key_type& k) : temporal_key(&k) {} member(const member& m) : temporal_key(m.temporal_key) { if (!temporal_key) { new (buffer) value_type(m.get_value()); } } ~member() { if (!temporal_key) { get_value().~value_type(); } } result_key_type get_key() const { return temporal_key ? *temporal_key : reference(get_value(), key); } value_type& get_value() { return *reinterpret_cast(buffer); } const value_type& get_value() const { return *reinterpret_cast(buffer); } bool operator ==(const member& m) const { return get_key() == m.get_key(); } bool operator !=(const member& m) const { return get_key() != m.get_key(); } bool operator < (const member& m) const { return get_key() < m.get_key(); } bool operator <=(const member& m) const { return get_key() <= m.get_key(); } bool operator > (const member& m) const { return get_key() > m.get_key(); } bool operator >=(const member& m) const { return get_key() >= m.get_key(); } value_type& operator *() { return get_value(); } const value_type& operator *() const { return get_value(); } value_type& operator ->() { return get_value(); } const value_type& operator ->() const { return get_value(); } operator value_type&() { return get_value(); } operator const value_type&() const { return get_value(); } operator result_key_type() const { return get_key(); } private: const key_type* const temporal_key; char buffer[sizeof(value_type)]; }; #endif // #ifndef MEMBER_HPP_INCLUDED /* // Test struct Klasa { explicit Klasa(const string& n) : nazwa(n), v(0) {} int v; string get_key() const { return "key_" + nazwa; } const string& get_nazwa() const { return nazwa; } const string nazwa; }; struct Szkola : public Klasa { explicit Szkola(const string& n) : Klasa(n) {} }; set > klasy1; klasy1.insert(Klasa("fajna klasa")); Klasa k1 = **klasy1.find(string("fajna klasa")); cout << k1.nazwa << endl; set > klasy2; klasy2.insert(new Klasa("fajna klasa")); Klasa* k2 = **klasy2.find(string("key_fajna klasa")); cout << k2->nazwa << endl; hash_set, const string& (Klasa::*)() const, &Klasa::get_nazwa>, hash_compare > szkoly; szkoly.insert(shared_ptr(new Szkola("fajna szkola"))); shared_ptr s = **szkoly.find(string("fajna szkola")); cout << s->nazwa << endl; //multiset, less > klasy4; hash_set, hash_compare > klasy4; klasy4.insert(Klasa("fajna klasa")); Klasa k4 = **klasy4.find(string("fajna klasa")); cout << k4.nazwa << endl; */