|
Boost : |
Subject: Re: [boost] boost::any_ref and boost::any_const_ref
From: Daniel Larimer (dlarimer_at_[hidden])
Date: 2010-02-14 16:05:13
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
>
>
>
>
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk