c++boostboost-any

boost::any confusion with pointers vs values


It took me a while to figure this out, but the semantics of boost::any are confusing.

With value types, you use it like so:

int value = 100;
boost::any something;
something = value;
//...later...
int value = boost::any_cast<int>(&something);

This code is clear and makes sense, but stores value internally as a copy. This means for larger objects I place inside boost::any, they will be copied. Also any functions that I replace void* with this will expect that the value outside the function is modified when I modify the value contained in the boost::any object (which won't happen, since it copied it).

So if I put pointers into it, things get weird:

int value = 100;
boost::any something;
something = &value;
//...later...
int* value = *boost::any_cast<int*>(&something);

I have to dereference the return value in this case because boost::any_cast returns int**! I also haven't checked but I think this may crash if something.empty() == true. This is just not straightforward at all.

I do not want to store values in my boost::any, I want it to only function on pointers and behave semantically closer to void*. Pointers in, pointers out, with some type-safety mixed in. Essentially what I want is boost::any_pointer, or something like that. Is there a way to prohibit boost::any from accepting anything except pointers? And if not, is there an alternative to boost::any that can give me the semantics I'm looking for?


Solution

  • You are using any_cast wrong:

    There are essentially two (three) flavors.

    Examples:

    #include <boost/any.hpp>
    int main()
    {
        // Any holding a value
        {
            boost::any any_value(1);
            // Throws bad_any_cast if the content is not 'int' (in this case):
            int  value = boost::any_cast<int>(any_value);
            // Throws bad_any_cast if the content is not 'int' (in this case):
            int& reference = boost::any_cast<int&>(any_value);
            // Returns a null pointer if the content is not 'int' (in this case):
            int* pointer = boost::any_cast<int>(&any_value);
        }
    
        // Any holding a pointer (which is nothing else but a value)
        {
            int integer = 0;
            boost::any any_ptr(&integer);
            // Throws bad_any_cast if the content is not 'int*' (in this case):
            int * pointer = boost::any_cast<int*>(any_ptr);
            // Throws bad_any_cast if the content is not 'int*' (in this case):
            int*& pointer_reference = boost::any_cast<int*&>(any_ptr);
            // Returns a null pointer if the content is not 'int*' (in this case):
            int** pointer_pointer = boost::any_cast<int*>(&any_ptr);
        }
    }
    

    See also: http://en.cppreference.com/w/cpp/experimental/any and http://en.cppreference.com/w/cpp/experimental/any/any_cast