
From: Martin Bidlingmaier <Martin.Bidlingmaier@gmx.de>
I've written a new version of boost::any. It does not depend on rtti and uses a static integer value instead of std::type_info to store type information.
Instead of reinventing the RTTI wheel. See following: There are 5 implementations of any using different methods linux windows boost 8.45 70.8 boost.any 1.46 any1 8.45 31.4 virtual impl->type() == typeid(Cast) any2 3.9 17.1 *this->type_ == typeid(Cast) any3 10.15 35.2 strcmp(this->type_->name(),typeid(Cast).name()) == 0 any4 4.5 12.5 this->type_ == &typeid(Cast) || *this->type_ == typeid(Cast) The first any implements the Boost.Any method - virtual call to get type compare to casted type and then cast. Other any2 to any 4 store pointer to typeid in the any object itself eliminating needless virtual call so any looks like { std::type_info const *type_; clone_ptr<impl> *impl; } 3 methods proposed: any2. compare types as is any3. compare names any4. compare pointer and then types. The 4th one should has the same efficiency as comparing integers and in fact on windows it was the fastest and on Linux comparing typeids was the fastest. What is good about it? 1. No virtual function calls at all 2. It is as fast as comparison of pointers or integers 3. It is fully dll/thread/standard safe and use native RTTI So... You want to improve any? Keep RTTI just use it in a smart way. Artyom Beilis -------------- CppCMS - C++ Web Framework: http://cppcms.sf.net/ CppDB - C++ SQL Connectivity: http://cppcms.sf.net/sql/cppdb/ ----------------------- any.h -------- #include <booster/clone_ptr.h> #include <typeinfo> #include <iostream> #include <string.h> #ifdef USE_BOOST #include <boost/any.hpp> using boost::any; using boost::any_cast; #elif defined(USE_ANY1) class any { struct impl { virtual std::type_info const &type() const = 0; virtual impl *clone() const = 0; virtual ~impl() {} }; template<typename T> struct impl_of : public impl{ impl_of(T const &v) : v_(v) {} virtual impl *clone() const { return new impl_of(*this); } virtual std::type_info const &type() const { return typeid(T); } T v_; }; public: template<typename T> any(T const &v) : o(new impl_of<T>(v)) { } any(any const &other) : o(other.o) {} any const &operator=(any const &other) { o = other.o; return *this; } template<typename V> V &cast() { if(o->type() == typeid(V)) return static_cast<impl_of<V> *>(o.get())->v_; throw std::bad_cast(); } private: booster::clone_ptr<impl> o; }; template<typename T> T &any_cast(any &v) { return v.cast<T>(); } #elif defined USE_ANY2 || defined USE_ANY3 || defined USE_ANY4 class any { struct impl { virtual impl *clone() const = 0; virtual ~impl() {} }; template<typename T> struct impl_of : public impl{ impl_of(T const &v) : v_(v) {} virtual impl *clone() const { return new impl_of(*this); } T v_; }; public: template<typename T> any(T const &v) : o(new impl_of<T>(v)), type(&typeid(T)) { } any(any const &other) : o(other.o) {} any const &operator=(any const &other) { o = other.o; return *this; } template<typename V> V &cast() { #ifdef USE_ANY3 if(strcmp(type->name(),typeid(V).name())==0) #elif defined(USE_ANY2) if(*type==typeid(V)) #elif defined USE_ANY4 if(type == &typeid(V) || *type==typeid(V)) #else #error #endif return static_cast<impl_of<V> *>(o.get())->v_; throw std::bad_cast(); } private: booster::clone_ptr<impl> o; std::type_info const *type; }; template<typename T> T &any_cast(any &v) { return v.cast<T>(); } #endif test.cpp ---------- #include "any.h" // prevent inlining int get_val(any &v); int main() { any a=int(2); int sum=0; for(int i=0;i<1000000000;i++) { sum+= get_val(a); } std::cout << sum << std::endl; } getval.cpp ---------- #include "any.h" int get_val(any &v) { return any_cast<int>(v); }