Boost :: any type change resulting in illegal access

When testing the examples through the boost cpp library book, I noticed that changing the type stored inside boost :: any variable can lead to illegal access instead of an exception:

well:

boost::any a = 1; bool *p = boost::any_cast<bool>(&a); // ok, bad cast exception 

badly:

 boost::any a = std::string { "Boost" }; a = 1; bool *p = boost::any_cast<bool>(&a); // no exception thrown std::cout << std::boolalpha << *p << '\n'; // illegal access 

So my question is: is this a mistake, as it seems, or is it some fundamental fact related to the use of templates that I do not know about?

+5
source share
1 answer

I understand the documentation in different ways:

Returns: If a pointer is passed, it returns a similarly qualified pointer to the contents of the value if successful, otherwise null is returned. If T is a ValueType, it returns a copy of the held value; otherwise, if T is a reference to a (possibly const) ValueType, it returns a reference to the held value.

Throws: Overloads using any pointer are not thrown; overloads that take any value or reference cause bad_any_cast if they are unsuccessful.

So:

  • The success or failure of the conversion depends on the type stored and the target type.

  • However, the manifestation of the failure depends on whether you pass a pointer to any_cast or not. If you pass a pointer, it will be nullptr ; otherwise it is an exception.

Consider, for example, this code:

 #include <boost/any.hpp> #include <iostream> int main() { boost::any a = 1; 

This seems to contradict the statement in your question - since it takes a pointer, it does not throw, but the pointer is nullptr :

  bool *p = boost::any_cast<bool>(&a); // Prints true std::cout << std::boolalpha << (p == nullptr) << std::endl; 

Here's what it looks like when it's OK:

  int *q = boost::any_cast<int>(&a); // Prints false std::cout << std::boolalpha << (q == nullptr) << std::endl; 

This calls because it does not accept a pointer:

  try { boost::any_cast<bool>(a); } catch(...) { std::cout << "caught" << std::endl; } 

The same goes for the saved string type:

  a = std::string { "Boost" }; p = boost::any_cast<bool>(&a); // Prints true std::cout << std::boolalpha << (p == nullptr) << std::endl; try { boost::any_cast<bool>(a); } catch(...) { std::cout << "caught again" << std::endl; } } 
+6
source

Source: https://habr.com/ru/post/1258138/


All Articles