dimanche 24 juillet 2022

C++11 - Keeping track of templated static storage of repeated types

I'm trying to create a flexible multi-track animation system using only C++11.

So far I have this code:

#include <vector>
#include <array>
#include <unordered_map>
#include <map>

template<typename T>
struct AnimationTrack
{
    using map_type = std::map<float, T>;
    map_type keyframes;

    AnimationTrack(std::initializer_list<typename map_type::value_type>&& keyframes) :
        keyframes(std::move(keyframes)) {}
};

template<typename T>
struct AnimationTrackView
{
    AnimationTrack<T>* track;

    AnimationTrackView() : 
        track(nullptr) {}

    AnimationTrackView(AnimationTrack<T>* track) :
        track(track) {}
};

template<typename... TrackTs>
class Animation
{
public:
    Animation(AnimationTrack<TrackTs>&... tracks)
    {
        StoreViews(tracks...);
    }

    template<std::size_t Index>
    auto& GetTrack()
    {
        return GetStorage<std::tuple_element<Index, std::tuple<TrackTs...>>::type>()[this].track;
    }

private:
    template<typename T>
    static auto& GetStorage()
    {
        static std::unordered_map<Animation*, AnimationTrackView<T>> storage;
        return storage;
    }

    template<typename T, typename... Ts>
    void StoreViews(AnimationTrack<T>& current, AnimationTrack<Ts>&... rest)
    {
        auto& storage = GetStorage<T>(); 
        storage.emplace(this, std::addressof(current));
        using expander = int[];
        (void)expander {
            0, (void(GetStorage<Ts>().emplace(this, std::addressof(rest))), 0)...
        };
    }
};


int main()
{
    AnimationTrack<float> test1(
    {
        { 0.2f, 1.0f },
        { 0.5f, 2.0f },
        { 0.9f, 3.0f }
    });

    AnimationTrack<int> test2(
    {
        { 0.2f, 1 },
        { 0.5f, 2 },
        { 0.9f, 3 }
    });

    Animation<float, int> anim(test1, test2);
    auto track0 = anim.GetTrack<0>();
    auto track1 = anim.GetTrack<1>();
}

This example works fine in this use case, but what if I wanted to keep two tracks of the same type? With my current code both tracks would grab from the same static storage when calling GetTrack, but the problem is I can't figure out a way to make it work with repeats of the same type. Any suggestions?

Aucun commentaire:

Enregistrer un commentaire