Boost logo

Boost :

Subject: Re: [boost] Interest in a container which can hold multiple data types?
From: James Armstrong (armstrhu_at_[hidden])
Date: 2015-05-11 12:07:08


On Mon, May 11, 2015 at 1:25 AM, Rob Stewart <rob.stewart_at_[hidden]>
wrote:

>
> Those aren't function pointers. They are function templates. You're on the
> right track, but you're not using overloading to your advantage. You need a
> get function template that is overloaded for the various holder types.
>
> namespace custom
> {
> template<class T>
> T &
> get(boost::any & _value)
> {
> return boost:: any_cast<T>(_value);
> }
> }
>
> You then write code like the following for your access:
>
> custom::get<T>(value);
>
> Regardless of the value type, be it any, variant, or what have you, with
> an appropriate overload of get(), you'd be able to extract the value. IOW,
> your code determines the interface(s) needed for common interactions with
> the holder types, and then it relies on specializations and/or overloads to
> adapt to the holder types.
>
> If one wants to use a new type with your container, one must specialize or
> overload the customization points you've chosen.
>
> It is possible to capture all customization points into a single policy
> class, but that can be less flexible in some cases. I'm not saying it isn't
> appropriate for your case. I'm just saying it isn't the right thing by
> default.
>
> In the example above, I've exposed the calling code to an exception should
> the any_cast fail. You have to decide whether that's acceptable and, if
> not, require your own exception type or have get return T*.
>

Sorry, I was spewing code without really saying much about it. I meant the
part that sets function pointers for each templated instance of
set_get_function<T> was,

p.set_get_function(get_boost_any<int>);
p.set_get_function(get_boost_any<double>);
p.set_get_function(get_boost_any<std::string>);

Internally, I have a vector of function pointers and the set_get_function
(I've renamed this to add_accessor<T>) will add the function pointer to the
vector. I see what you are saying about making a get function, it would
work in a very similar fashion as get<>(std::tuple). However, I'd like to
provide an iterator, and for that I need a function internal to the class
which can get the transform the type-erased data to the native(?) data
type. For example, my dereference operator needs a way to transform the
boost::any/boost::variant/etc into the native data type. As is, I use the
function pointer to use the user defined function to accomplish that.
Without that, I am not sure if it is possible to provide an iterator since
its not possible to know the method to transform any generic type-erased
datatype. I am not aware of any other method to allow the user to insert a
function that my class can use internally. Providing a
custom::get<T>(value) I think is key, but allowing iteration with a clean
syntax would be super nice as well. Currently, this is my syntax,

//define templated accessor function
template<typename T>
void* boost_any_accessor(boost::any* b)
{
    return (void*)boost::any_cast<T>(b);
}

int main()
{
    typedef boost::any data_type data_type;
    typedef std::vector<data_type> container_type;

    container_type container;
    container.push_back(3.1415f);
    container.push_back(3.14159);
    container.push_back(std::string("a"));
    container.push_back(2.71828);
    container.push_back(std::string("b"));

    test::poly_adaptor<container_type> p(container);

    /*
    * Add data accessor function pointers
    *
    * An accessor function needs to be added for each data type to be
    * retrieved, but not necessarily for each type stored in container.
    */
    p.add_accessor<std::string>(boost_any_accessor<std::string>);
//provides access to std::string

    //iterate over std::strings
    for (auto itr = p.begin<std::string>(); itr != p.end<std::string>();
++itr)
    {
        std::cout << *itr << std::endl;
    }
    std::cout << std::endl;
}

I think its a relatively clean syntax, but I'd take any suggestions for
improvement, or clarification if I'm misunderstanding. I'll work on
creating that get<T>(value) function also. Thanks for the feedback.

-- 
James Armstrong

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk