Both the GCC and LLVM implementations of std::any store a function pointer in the any object and call that function with an Op/Action argument to perform different operations. Here is an example of that function from LLVM:
static void* __handle(_Action __act, any const * __this,
any * __other, type_info const * __info,
void const* __fallback_info)
{
switch (__act)
{
case _Action::_Destroy:
__destroy(const_cast<any &>(*__this));
return nullptr;
case _Action::_Copy:
__copy(*__this, *__other);
return nullptr;
case _Action::_Move:
__move(const_cast<any &>(*__this), *__other);
return nullptr;
case _Action::_Get:
return __get(const_cast<any &>(*__this), __info, __fallback_info);
case _Action::_TypeInfo:
return __type_info();
}
__libcpp_unreachable();
}
Note: This is just one __handle function but there there are two such functions in each any implementation: one for small objects (Small buffer optimization) allocated within any and one for big objects allocated on the heap. Which one is used depends on the value of the function pointer stored in the any object.
The ability to choose one of two implementations at run-time and call a specific method from a pre-defined list of methods is essentially a manual implementation of a virtual table. I'm wondering why it was implemented this way. Wouldn't it have been easier to simply store a pointer to a virtual type?
I couldn't find any information about the reasons for this implementation. Thinking about it, I guess using a virtual class is sub-optimal in two ways:
- It needs an object instance and managing a singleton, whereas in reality a vtable (without an instance) is enough.
- Calling a function on
anywould involve two indirections: first through the pointer stored inanyto get the vtable, then through the pointer stored in the vtable. I'm not sure if the performance of this is any different to theswitch-based approach above.
Are these the reasons for using an implementation based on switch-ing op-codes? Is there any other major advantage of the current implementation? Do you know of a link to general information about this technique?