C ++-type caching without using static storage

I am using something like:

struct VectorCache { template<typename T> std::vector<T>& GetTs() { static std::vector<T> ts; return ts; } }; 

to create / access some vectors based on the specified type. This works fine as long as I only have one object of type VectorCache , but when I use multiple objects, I get the same vectors from all instances of VectorCache , since the vectors are static variables.

I tried moving vectors as member variables using something similar to boost::any and accessing them using std::type_index for T, but it was somehow slower than the direct access I used before.

Other options are converting the struct VectorCache to something like template<int index> struct VectorCache , but the problem still exists - I need to be careful to have only one instance / index in order to have the correct behavior.

Is it possible to access vectors directly based on T , and also use a caching instance instead of a class?

+5
source share
2 answers

You can try the uncontrolled analogue of Boost.Any. See if this is enough for you (although I don’t believe that it will make a big difference):

 #include <memory> #include <type_traits> #include <typeindex> #include <unordered_map> #include <vector> class AnyCache { struct TEBase { virtual ~TEBase() {} virtual void * get() = 0; }; template <typename T> struct TEObject : TEBase { T obj; virtual void * get() override { return static_cast<void *>(&obj); } }; std::unordered_map<std::type_index, std::unique_ptr<TEBase>> cache; public: AnyCache(AnyCache const &) = delete; AnyCache & Operator=(AnyCache const &) = delete; template <typename T> decltype(auto) get() { using U = std::decay_t<T>; using C = std::vector<U>; std::unique_ptr<TEBase> & p = cache[typeid(U)]; if (!p) { p = std::make_unique<TEObject<C>>(); } return *static_cast<C *>(p->get()); } }; 

Using:

 AnyCache ac; ac.get<int>().push_back(20); ac.get<std::string>().push_back("Hello"); for (auto const & x : ac.get<Foo>()) { std::cout << x << '\n'; } 
+5
source

If - and this is big, if - your VectorCache code is not VectorCache , you can do this:

 struct VectorCache { VectorCache() : instance_counter_(++s_instance_counter_) { } template<typename T> std::vector<T>& GetTs() { static std::vector<std::vector<T>> tss; if (tss.size() <= instance_counter_) tss.resize(instance_counter_); return tss[instance_counter_]; } size_t instance_counter_; static size_t s_instance_counter_; }; // and define size_t VectorCache::s_instance_counter_; 

implementation on ideone.com

With a little synchronization, you can make it thread safe or even a specific thread if that suits you. Add delete construction / destination copy, etc., if that makes sense in your intended use.

+2
source

Source: https://habr.com/ru/post/1204643/


All Articles