Q:

Modern way to have a map that can point-to or reference data of different types that has been allocated on the stack

Using raw pointers, this can be achieved like so:
#include <iostream>
#include <string>
#include <map>

using namespace std;

class base {
public:
    virtual ~base(){}
};

class derived1 : public base {
public:
    virtual ~derived1(){}
    derived1(const int& other) : val(other) {}
    int val;
};

class derived2 : public base {
public:
    virtual ~derived2(){}
    derived2(const float& other) : val(other) {}
    float val;
};

int main()
{
    derived1 dataA = 4;
    derived2 dataB = 3.0f;

    std::map<std::string, base*> mapOfPointersToData; //Needs to be a pointer because it can be of type deribed1 or derived2. Cant be smart as pointing to stack memory
    mapOfPointersToData["dataA"] = &dataA;
    mapOfPointersToData["dataB"] = &dataB;

    base* result = mapOfPointersToData["dataA"];

    std::cout << dynamic_cast<derived1*>(result)->val << std::endl;

    return 0;
}

This works, but I have been told that we should avoid the use of raw pointers in favour of smart pointers or references.
The objects can never be null, so it makes sense to use a reference. We can get around the problem that the map can only store one data type by using a variant:
int main()
{
    derived1 dataA = 4;
    derived2 dataB = 3.0f;

    std::map<std::string, std::variant<derived1, derived2>&> mapOfPointersToData; //Cant be constructed
    mapOfPointersToData["dataA"] = dataA;
    mapOfPointersToData["dataB"] = dataB;

    auto result = mapOfPointersToData["dataA"];

    std::cout << std::get<derived1>(result).val << std::endl;

    return 0;
}

but this gives the error
error: value-initialization of reference type ‘std::variant<derived1, derived2>&

So what is the best way to store references to stack data that can be of different types?

A:

This works, but I have been told that we should avoid the use of raw pointers in favour of smart pointers or references.

Raw pointers are only discouraged when they are responsible for owning what they point to (essentially, if you have to remember to delete or otherwise release them). Here, the objects have automatic storage duration and the pointers aren't responsible for cleaning them up. This is a reasonable use case for raw pointers.

The objects can never be null, so it makes sense to use a reference.

Objects in your map might be nullptr if you use operator[] to search the map. That operator adds any element it fails to find and value initializes them (to nullptr for pointers). You can use find instead if you don't want to bloat your map with empty pointers.

So what is the best way to store references to stack data, that can be of different types?

You might be looking for std::reference_wrapper which wraps references in an object that is suitable for containers. But using base* seems like a fine solution already, because your map doesn't own the objects it ultimately points to.

