Boost logo

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