C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Language support for type erasure

From: Simon Schröder <dr.simon.schroeder_at_[hidden]>
Date: Sun, 12 Apr 2026 16:29:14 +0200
I’m thinking about reflection in this context. Herb Sutter already suggested meta classes as a reflection concept. I’m not entirely sure if I remember this correctly, but I believe one of his examples was that we write an interface class (one where there are only declarations of member methods, but no definitions). With a meta class (basically a compile time function that is applied to your own class) we could automatically create your Animal class.

BTW, I believe typedef is dead and using is the new hero in town. Though if the use of traditional typedef fades out eventually we might be able to reuse the keyword in the future. But, does C have ‘using’ now? Or still just typedef? In the latter case we will still have plenty of code with the traditional meaning of typedef.

> On Apr 10, 2026, at 11:39 AM, Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> In a job interview recently I was given the following code:
>
> #include <iostream>
> #include <memory>
> #include <string>
>
> struct Animal {
> virtual ~Animal() = default;
> virtual std::string name() const = 0;
> };
>
> struct Cat : Animal {
> std::string name(void) const override
> {
> return "Cat";
> }
> };
>
> struct Dog : Animal {
> std::string name(void) const override
> {
> return "Dog";
> }
> };
>
> /* DO NOT CHANGE THE CODE BELOW! */
>
> void print_name(Animal const &a)
> {
> std::cout << a.name() << std::endl;
> }
>
> int main(void)
> {
> Cat cat;
> Dog dog;
> print_name(cat);
> print_name(dog);
> }
>
> I was told to remove the inheritance, but I wasn't allowed to edit
> code beneath the indicated line. So here's what I gave them back:
>
> struct Cat {
> string name(void) const
> {
> return "Cat";
> }
> };
>
> struct Dog {
> string name(void) const
> {
> return "Dog";
> }
> };
>
> struct Animal {
> std::function< string(void) > name;
>
> template<typename T>
> Animal(T &&arg)
> {
> name = [&arg](void){ return arg.name(); };
> }
> };
>
> Now let's consider if there were multiple member functions:
>
> struct Cat {
> string name(void) const
> {
> return "Cat";
> }
> string weight(void) const
> {
> return "4kg";
> }
> string height(void) const
> {
> return "20cm";
> }
> };
>
> struct Dog {
> string name(void) const
> {
> return "Dog";
> }
> string weight(void) const
> {
> return "12kg";
> }
> string height(void) const
> {
> return "50cm";
> }
> };
>
> struct Animal {
> std::function< string(void) > name;
> std::function< string(void) > weight;
> std::function< string(void) > height;
>
> template<typename T>
> Animal(T &&arg)
> {
> name = [&arg](void){ return arg.name (); };
> weight = [&arg](void){ return arg.weight(); };
> height = [&arg](void){ return arg.height(); };
> }
> };
>
> Instead of having multiple functor objects, we could do something like:
>
> struct Animal {
> std::function< string(unsigned) > f;
>
> template<typename T>
> Animal(T &&arg)
> {
> f =
> [&arg](unsigned const n) -> string
> {
> switch ( n )
> {
> case 0: return arg.name ();
> case 1: return arg.weight();
> case 2: return arg.height();
> }
> };
> }
>
> string name (void) const { return f(0); }
> string weight(void) const { return f(1); }
> string height(void) const { return f(2); }
> };
>
> This got me thinking . . . . Should we have native language support for this?
> For example let's say we were to define a class with the interface that we want:
>
> struct Interface {
> string name(void) const;
> string weight(void) const;
> string height(void) const;
> };
>
> And then perhaps we would have a new kind of 'typedef' that creates
> the type-erased class, something like:
>
> typedef<Interface> TypeErasedType;
>
> And so then the entire program would look something like this:
>
> #include <iostream>
> #include <functional>
> #include <string>
> #include <utility>
> using std::string;
>
> struct Cat {
> string name(void) const
> {
> return "Cat";
> }
> string weight(void) const
> {
> return "4kg";
> }
> string height(void) const
> {
> return "20cm";
> }
> };
>
> struct Dog {
> string name(void) const
> {
> return "Dog";
> }
> string weight(void) const
> {
> return "12kg";
> }
> string height(void) const
> {
> return "50cm";
> }
> };
>
> struct Interface {
> string name(void) const;
> string weight(void) const;
> string height(void) const;
> };
>
> typedef<Interface> Animal;
>
> /* DO NOT CHANGE THE CODE BELOW! */
>
> void print_name(Animal const &a)
> {
> std::cout << a.name () << std::endl;
> std::cout << a.weight() << std::endl;
> std::cout << a.height() << std::endl;
> }
>
> int main()
> {
> Cat cat;
> Dog dog;
> print_name(cat);
> print_name(dog);
> }
>
> Another nice thing about this is that we would get a very intuitive
> compiler warning if the supplied type doesn't fulfil all the criteria
> of the type-erased type -- it can clearly tell us that the supplied
> type is missing a member function that's required for the interface.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2026-04-12 14:29:29