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?
NOTE : I am assuming you want to store pointers in boost::any
, since you are looking for something on the lines of boost::any_pointer
(though non-existent).
boost::any_cast
returns the pointer to the actual value stored inside it (the held
object inside holder). So it kind of saves a copy unless you actually want to copy it later.
template<typename ValueType>
ValueType * any_cast(any * operand) BOOST_NOEXCEPT
{
return operand && operand->type() == boost::typeindex::type_id<ValueType>()
? &static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held
: 0;
}
You can always create a wrapper around boost::any
to allow only pointer types:
class MyAny {
public:
template <typename T,
typename = typename std::enable_if<std::is_pointer<std::remove_cv<T>::type>::value>::type>
MyAny(T ptr): any_(ptr) {}
template <typename ValueType>
ValueType operator*() {
return *boost::any_cast<ValueType>(&any_);
}
private:
boost::any any_
};
Above is a rough code, I have not compiled and tested it.
std::enable_if
type trait is available in C++11, but can be found in boost as well. It is what that will constrain your MyAny
to only pointer types.
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
Although this is quite an old question, I nevertheless would like to point out a simple misconception [I think] in the preface of the asked questions:
int value = 100;
boost::any something;
something = &value; // 1)
//...later...
int* value = *boost::any_cast<int*>(&something); // 2)
1) This saved "int *" in something.
2) This contains essentially several steps:
What I think, void.pointer wanted to do here, is more along the following line:
int* value = boost::any_cast<int*>(something);
.
PS: I would have liked to put this in a simple comment and not a full-fledged answer - stackoverflow however requires me to collect enough points first, so...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.