C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Extend std::type_info with more information

From: Tiago Freire <tmiguelf_at_[hidden]>
Date: Thu, 11 Apr 2024 18:54:30 +0000
From my perspective the use cases for std::any are dubious at best.


Fair warning this is going to be lengthy.


It is essentially a container that can have anything at all.

I think I would be hard to find a usage of it that doesn’t fall into one of these categories:

1. The context in which it is being used, doesn’t care about the underlying type nor uses its value. Making any type_info or casting irrelevant.

2. The context in which it is being used, knows exactly what type to expect, and the object has gone trough an intermediate context of type 1. Making the type_info just as a means of validation, and casting can be done trivially.

3. The design could have been improved by using a less type erased container (ex. std::variant, or other). Making std::any a design issue, and not a good use case.


An application that only contains type 1 is irrelevant, if the value is never used, you don’t need a container for it, so the code could be improved by using a “nothing” (making it a type 3).
There’s a minimum requirement that at least the value be used, and usage of the value requires at least some basic form of interface, it must have a basic set of expected properties. Using the value the type can’t just literally be anything. This kind of suggest std::variant would be better, to justify not being able to use it you are going to have somewhere in code where the objects passes that requires complete type erasure (a usage of type 1 must exist somewhere).
Now while this isn’t necessarily of type 2, something very much like it must be true.

Now to justify std::any, type 1 needs to exist somewhere, this is already very very rare. And it would be rarer still that you need to use it and the use case is not of type 2.
I don’t think the use case where it could literally be anything, and then you can just swap it for absolutely anything else mid execution and still make proper use of it, is realistic. There must be some properties about the type that must be true to be realistically useful.

What I believe is type most applications that use std::any are actually of type 3.
And I don’t mean that std::variant is necessarily the right replacement here.

std::any does 2 things:
1. own an object. Any object. It controls the lifetime of the object.
2. erase the type of the selected object.

The task of owning an object can be implemented by having a template constructor, allocate the object, storing it, and storing a custom deleter. This is trivial I assume everyone knows how to implement this, this shouldn’t be a controversial idea.

While type erasure is useful in many circumstances do you always need absolute type erasure? Wouldn’t partial be sufficient in most cases?
Let’s say you don’t need to know which exact derived class you are using; you just need to know that it is derived from a base class.

For that I could design a templated class, let’s call it “doppelganger”, that can contain an object of a “derived” class but only presents itself as an interface to a “base” class.
i.e.

class A{};
class B: public A {};

std::doppelganger<A> tracked_object = B{};

// tracked_object can be used as A, but is an object of type B //this is a pure liskov abstraction

Kind of like what you already can do with std::unique_ptr but with value semantics instead.


This will perhaps be a far better design for the widget example. It has forgotten about what specialization of widget it is, but it can’t just be absolutely anything. We still know it is a widget.
And we have the added benefit of keeping some semblance of type safety, you can cast it by trivial means, either by dynamic_cast if base has a vtable, or even static_cast if the user has created its own RTTI for this object absent of a vtable.


If you had this ^, would you really still need to use std::any?
What if you could combine std::doppelganger with std::any, would you really still need to cast directly from std::any? (i.e. still absent of any knowledge of the underlying type)

Received on 2024-04-11 18:54:37