std::any without RTTI, how does it work?

  • A+
Category:Languages

If I want to use std::any I can use it with RTTI switched off. The following example compiles and runs as expected also with -fno-rtti with gcc.

int main() {        std::any x;     x=9.9;     std::cout << std::any_cast<double>(x) << std::endl; } 

But how std::any stores the type information? As I see, if I call std::any_cast with the "wrong" type I got std::bad_any_cast exception as expected.

How is that realized or is this maybe only a gcc feature?

I found that boost::any did also not need RTTI, but I found also not how that is solved. Does boost::any need RTTI?.

Digging into the STL header itself gives me no answer. That code is nearly unreadable to me.

 


TL;DR; std::any holds a pointer to a static member function of a templated class. This function can perform many operations and is specific to a given type since the actual instance of the function depends on the template arguments of the class.


The implementation of any in libstdc++ is not that complex, you can have a look at it:

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/any

Basically, std::any holds two things:

  • A pointer to a dynamically allocated storage;
  • A pointer to a "storage manager function":
void (*_M_manager)(_Op, const any*, _Arg*); 

When you construct or assign a new std::any with an object of type T, _M_manager points to a function specific to the type T (which is actually a static member function of class specific to T):

template <typename _ValueType,            typename _Tp = _Decay<_ValueType>,           typename _Mgr = _Manager<_Tp>, // <-- Class specific to T.           __any_constructible_t<_Tp, _ValueType&&> = true,           enable_if_t<!__is_in_place_type<_Tp>::value, bool> = true> any(_ValueType&& __value)   : _M_manager(&_Mgr::_S_manage) { /* ... */ } 

Since this function is specific to a given type, you don't need RTTI to perform the operations required by std::any.

The class _Manager<_Tp> is actually an alias to either _Manager_internal<_Tp> or _Manager_external<_Tp> depending on _Tp. This class is also used for allocation / construction of object for the std::any class.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: