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]>

> 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,


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;

    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.
//provides access to std::string

    //iterate over std::strings
    for (auto itr = p.begin<std::string>(); itr != p.end<std::string>();
        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, gregod at, cpdaniel at, john at