boost::any_ref and boost::any_const_ref

I am attempting to create a library with a generic interface run-time interface and have need for something like boost::any; however, boost::any requires heap allocation. boost::variant is not acceptable either because I do not know the full set of types in advance. Has anyone seen the equivalent of a type-checked void* or const void*? Effectively I would like to create a polymorphic method like this: void myclass::method( const_any_ref p1, const_any_ref p2, const any_ref p3 ) { const uint16_t& _p1 = p1; const double& _p2 = p2; const std::string& _p3 = p3; //If any of the types do not match it should throw an exception. alternatively the follow syntax may work if you want to avoid exceptions? boost::optional<const uint16_t&> _p1 = p1; if( !_p1 ) // cast failed? } Anyone have any nifty ideas on how to accomplish this without RTTI and no heap allocation? In place of RTTI I do have a "manual" RTTI system that I could use. get_typename<T>::str will return a unique const char* pointer. I am guessing the best I can hope for is a pair of pointers, one "void*" and one const char*. I am going to write such a class unless someone here knows of an existing solution. Dan

Here is my implementation for review. I haven't determined if I need to do some kind of check on assignment / copy construction. In theory this could allow you to return a reference to a temporary without warning and thus if you are not "sure" that your object will remain on the stack for the life of the const_any_ref then extra steps may need to be taken. So the question is, should I disable the ability to copy construct and thus force const_any_ref to be passed by const&, thus making function signatures: void method( const const_any_ref& parameter ); OR I could rename const_any_ref to something like detail::const_any_ref and then typedef const detail::const_any_ref& const_any_ref Dan #ifndef _ANYREF_HPP #define _ANYREF_HPP #include <boost/optional.hpp> // this template may be specialized if you do not want to // use RTTI to determine type name template< typename T> template<> struct get_typename { static const char* str; }; #ifdef USE_RTTI template<typename T> const char* get_typename<T>::str = typeid(T).name(); #endif #define DEFINE_GETTYPENAME(...) \ template<> struct get_typename<__VA_ARGS__> { static const char* str; }; \ const char* get_typename<__VA_ARGS__>::str = #__VA_ARGS__; class const_any_ref { public: template<typename T> const_any_ref( const T& v ) :ref(&v), typestr(get_typename<T>::str) { } const_any_ref() :ref(NULL),typestr(NULL) { } const char* type()const { return typestr; } template<typename T> inline operator T()const { return (const T&)(*this); } template<typename T> inline operator const T&()const { assert( typestr == get_typename<T>::str ); assert( ref != NULL ); return *((const T*)ref); } template<typename T> inline operator boost::optional<const T&>()const { if( typestr == get_typename<T>::str && ref ) return *((const T*)ref); return boost::optional<const T&>(); } private: const void* ref; const char* typestr; }; class any_ref { public: template<typename T> any_ref( T& v ) :ref(&v), typestr(get_typename<T>::str) { } any_ref() :ref(NULL),typestr(NULL) { } const char* type()const { return typestr; } template<typename T> inline operator T()const { return (T&)(*this); } template<typename T> inline operator T&()const { assert( typestr == get_typename<T>::str ); assert( ref != NULL ); return *((T*)ref); } template<typename T> inline operator boost::optional<T&>()const { if( typestr == get_typename<T>::str && ref ) return *((T*)ref); return boost::optional<T&>(); } private: void* ref; const char* typestr; }; #endif int test_add( const_any_ref p1, const_any_ref p2 ) { boost::optional<const int&> _p1 = p1; const int& _p2 = p2; return *_p1 + _p2; } void test_add( const_any_ref p1, const_any_ref p2, any_ref rtn ) { int& _rtn = rtn; _rtn = int(p1) + int(p2); } int main( int argc, char**argv ) { printf( "%d + %d = %d\n", 1, 2, test_add(int(1),int(2)) ); int rtn; test_add(int(1),int(2),rtn); printf( "1 + 2 = %d\n", rtn ); return 0; } On Feb 14, 2010, at 2:23 PM, Daniel Larimer wrote:
I am attempting to create a library with a generic interface run-time interface and have need for something like boost::any; however, boost::any requires heap allocation. boost::variant is not acceptable either because I do not know the full set of types in advance.
Has anyone seen the equivalent of a type-checked void* or const void*?
Effectively I would like to create a polymorphic method like this:
void myclass::method( const_any_ref p1, const_any_ref p2, const any_ref p3 ) { const uint16_t& _p1 = p1; const double& _p2 = p2; const std::string& _p3 = p3;
//If any of the types do not match it should throw an exception.
alternatively the follow syntax may work if you want to avoid exceptions? boost::optional<const uint16_t&> _p1 = p1; if( !_p1 ) // cast failed? }
Anyone have any nifty ideas on how to accomplish this without RTTI and no heap allocation?
In place of RTTI I do have a "manual" RTTI system that I could use.
get_typename<T>::str will return a unique const char* pointer.
I am guessing the best I can hope for is a pair of pointers, one "void*" and one const char*.
I am going to write such a class unless someone here knows of an existing solution.
Dan
participants (1)
-
Daniel Larimer