/* try.cpp - for trying out some language features.... * scons will create the binary bin/try * */ // 8/07 - how to control NOBUG?? // execute with NOBUG_LOG='ttt:TRACE' bin/try // 1/08 - working out a static initialisation problem for Visitor (Tag creation) // 1/08 - check 64bit longs // 4/08 - comparison operators on shared_ptr // 4/08 - conversions on the value_type used for boost::any // 5/08 - how to guard a downcasting access, so it is compiled in only if the involved types are convertible #include #include #include #include #include #include #include #include #include using std::string; using std::cout; using std::ostream; using boost::remove_pointer; using boost::remove_reference; using boost::is_convertible; using boost::is_polymorphic; using boost::is_base_of; using boost::enable_if; template struct can_cast : boost::false_type {}; template struct can_cast { enum { value = is_base_of::value };}; template struct can_cast { enum { value = is_base_of::value };}; template struct can_cast { enum { value = is_base_of::value };}; template struct has_RTTI { typedef typename remove_pointer< typename remove_reference::type>::type TPlain; enum { value = is_polymorphic::value }; }; template struct use_dynamic_downcast { enum { value = can_cast::value && has_RTTI::value && has_RTTI::value }; }; template struct use_static_downcast { enum { value = can_cast::value && ( !has_RTTI::value || !has_RTTI::value ) }; }; template struct use_conversion { enum { value = is_convertible::value && !( use_static_downcast::value ||use_dynamic_downcast::value ) }; }; template struct EmptyVal { static X create() { cout << " NULL() " << __PRETTY_FUNCTION__ <<"\n"; return X(); } }; template struct EmptyVal { static X*& create() { cout << " NULL & " << __PRETTY_FUNCTION__ <<"\n"; static X* null(0); return null; } }; template struct NullAccessor { typedef RET Ret; static RET access (...) { return ifEmpty(); } static RET ifEmpty () { return EmptyVal::create(); } }; template struct AccessCasted : NullAccessor { using NullAccessor::access; template static typename enable_if< use_dynamic_downcast, TAR>::type access (ELM& elem) { cout << " dynamic " << __PRETTY_FUNCTION__ <<"\n"; return dynamic_cast (elem); } template static typename enable_if< use_static_downcast, TAR>::type access (ELM& elem) { cout << " static " << __PRETTY_FUNCTION__ <<"\n"; return static_cast (elem); } template static typename enable_if< use_conversion, TAR>::type access (ELM& elem) { cout << " convert " << __PRETTY_FUNCTION__ <<"\n"; return elem; } }; struct B {}; struct D : B {}; struct E : D { virtual ~E() {}; }; struct F : E {}; ostream& operator<< (ostream& s, const B& b) { return s << "B{} adr="<<&b; } ostream& operator<< (ostream& s, const D& d) { return s << "D{} adr="<<&d; } ostream& operator<< (ostream& s, const E& e) { return s << "E{} adr="<<&e; } ostream& operator<< (ostream& s, const F& f) { return s << "F{} adr="<<&f; } int main (int argc, char* argv[]) { NOBUG_INIT; D d; D* pD =&d; B* pB =pD; D& rD = *pD; B& rB = *pB; D*& rpD = pD; B*& rpB = pB; F f; E& rE = f; E* pE = &f; D* pDE = pE; cout << "is_base_of = " << is_base_of::value << "\n"; cout << "is_base_of = " << is_base_of::value << "\n"; cout << "is_base_of = " << is_base_of::value << "\n"; cout << "can_cast = " << can_cast::value << "\n"; cout << "can_cast = " << can_cast::value << "\n"; cout << "can_cast = " << can_cast::value << "\n"; cout << "can_cast = " << can_cast::value << "\n"; cout << "can_cast = " << can_cast::value << "\n"; cout << "can_cast = " << can_cast::value << "\n"; cout << "can_cast = " << can_cast::value << "\n"; cout << "can_cast = " << can_cast::value << "\n"; cout << "can_cast = " << can_cast::value << "\n"; cout << "has_RTTI = " << has_RTTI::value << "\n"; cout << "has_RTTI = " << has_RTTI::value << "\n"; cout << "has_RTTI = " << has_RTTI::value << "\n"; cout << "use_dynamic_downcast = " << use_dynamic_downcast::value << "\n"; cout << "use_static_downcast = " << use_static_downcast::value << "\n"; cout << "use_conversion = " << use_conversion::value << "\n"; cout << "use_static_downcast = " << use_static_downcast::value << "\n"; cout << "use_static_downcast = " << use_static_downcast::value << "\n"; cout << "use_dynamic_downcast = " << use_dynamic_downcast::value << "\n"; cout << "Access(D as D&) --->" << AccessCasted::access(d) << "\n"; cout << "Access(D& as D&) --->" << AccessCasted::access(rD) << "\n"; cout << "Access(B& as D&) --->" << AccessCasted::access(rB) << "\n"; cout << "Access(D* as D*) --->" << AccessCasted::access(pD) << "\n"; cout << "Access(B* as D*) --->" << AccessCasted::access(pB) << "\n"; cout << "Access(D*& as D*&) --->" << AccessCasted::access(rpD) << "\n"; cout << "Access(B*& as D*&) --->" << AccessCasted::access(rpB) << "\n"; cout << "Access(D as B&) --->" << AccessCasted::access(d) << "\n"; cout << "Access(D& as B&) --->" << AccessCasted::access(rD) << "\n"; cout << "Access(B& as B&) --->" << AccessCasted::access(rB) << "\n"; cout << "Access(D* as B*) --->" << AccessCasted::access(pD) << "\n"; cout << "Access(B* as B*) --->" << AccessCasted::access(pB) << "\n"; cout << "Access(D*& as B*&) --->" << AccessCasted::access(rpD) << "\n"; cout << "Access(B*& as B*&) --->" << AccessCasted::access(rpB) << "\n"; cout << "Access(D as E&) --->" << AccessCasted::access(d) << "\n"; cout << "Access(E& as F&) --->" << AccessCasted::access(rE) << "\n"; cout << "Access(D(E)* as E*) --->" << AccessCasted::access(pDE) << "\n"; cout << "Access(D(E)* as F*) --->" << AccessCasted::access(pDE) << "\n"; cout << "Access(E* as F*) --->" << AccessCasted::access(pE) << "\n"; cout << "\ngulp\n"; return 0; }