I'm 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 contained type. This works fine as long as I have only one object of type VectorCache
, but when I use multiple objects I will get same vectors from all instances of VectorCache
as the vectors are static variables.
I tried to move the vectors as member variables using something similar to boost::any
and access them using std::type_index
of T, but this is somehow slower than the direct access I used before.
Another options is to transform struct VectorCache
to something like template<int index> struct VectorCache
, but the problem is still there - I will have to be careful to have only one instance/index to have correct behaviour.
Is it possible to access the vectors directly based on T
and also have the caching instance based instead of class based?
You could try an unchecked analogue of Boost.Any. See if that's fast enough for you (though I don't believe it would 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());
}
};
Usage:
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'; }
If - and it's a big if - your VectorCache
-using code isn't threaded, 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 synchronisation you can make it thread safe, or even thread specific if that suits. Add deletion of copy construction / assignment etc. if that makes sense in your intended usage.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With