I want a library that offers an in-memory data structure,such that I can write,for example:
cache.insert(key,value,expiry)
and I can retrieve the value with something like cache[key],unless it has passed expiry seconds.
Can be done? What library should I use?
Prefer libraries for D,if possible
I'm unaware of any library that does this. On the other hand, it's not a lot of work to get something working. Here's something I threw together in ten minutes:
struct Dict(K, V, E)
if (isExpiry!E)
{
import std.typecons : Tuple;
private:
Tuple!(V, "value", E, "expiry")[K] _payload;
public:
V opIndex(K key)
{
return *(key in this);
}
V* opBinaryRight(string op : "in")(K key)
{
auto p = key in _payload;
if (!p || p.expiry.expired) return null;
return &p.value;
}
void insert(K key, V value, E expiry)
{
expiry.initialize();
_payload[key] = typeof(_payload[key])(value, expiry);
}
void remove(K key)
{
_payload.remove(key);
}
}
enum isExpiry(T) = is(typeof((T t){
t.initialize();
if (t.expired) {}
}));
static assert(!isExpiry!int);
struct Timeout
{
import core.time;
Duration duration;
MonoTime start;
void initialize() {
start = MonoTime.currTime;
}
#property
bool expired()
{
auto elapsed = MonoTime.currTime - start;
return elapsed > duration;
}
}
static assert(isExpiry!Timeout);
unittest
{
import core.time;
import core.thread;
Dict!(int, string, Timeout) a;
assert(3 !in a);
a.insert(3, "a", Timeout(100.dur!"msecs"));
a.insert(4, "b", Timeout(10.dur!"days"));
assert(3 in a);
assert(4 in a);
Thread.sleep(200.dur!"msecs");
assert(3 !in a);
assert(4 in a);
a.remove(4);
assert(4 !in a);
}
Related
I'm trying to implement json serialization of a class using eigen::VectorXd and nlohmann-json library. It's not a problem to store the class as JSON string. How to parse VectorXd from JSON? Is there an other library more suitable for this task?
#include "json.hpp"
class TransformationStep {
public:
VectorXd support_vector;
int number;
TransformationStep(int number_param, VectorXd support_vectorParam) {
number = number_param;
support_vector = support_vectorParam;
}
~TransformationStep() {
}
//json serialization
void to_json(nlohmann::json &j);
void from_json(const nlohmann::json &j);
};
void TransformationStep::to_json(nlohmann::json &j) {
j["number"] = number;
j["support_vector"] = support_vector;
}
void Ftf::from_json(const nlohmann::json &j)
{
number = (j.at("number").get<int>());
//support_vector = j["support_vector"].get<VectorXd>()); //???
}
------ output calling to_json(nlohmann::json &j) ------
{
"number": 3,
"support_vector": [
-0.00036705693279489064,
0.020505439899631835,
0.3531380358938106,
0.0017673029092790872,
-0.9333248513057808,
0.04670404618976708,
-0.21905858722244081,
-1.011945322347849,
-0.09172040021815037,
0.008526811888809391,
0.05187648010664058
]
}
I came up with
void vector_from_json(VectorXd& vector, const nlohmann::json &j) {
vector.resize(j.size());
size_t element_index=0;
for (const auto& element : j) {
vector(element_index++) = (double) element;
}
}
For example, if I have a bool value v, I want a reference to !v that can change when v changes. An example use will be:
class A {
bool& isOpen;
A(bool& value): isOpen(value) {}
void f() {
if (isOpen) {
doSomething();
}
}
};
class B {
bool& isClosed;
B(bool& value): isClosed(value) {}
void g() {
if (isClosed) {
doSomething();
}
}
};
int main() {
bool isOpen = true;
A a(isOpen);
B b(negattive_reference_of(isOpen));
a.f(); // doSomething()
b.g(); // do nothing
isOpen = false;
a.f(); // do nothing
b.g(); // doSomething()
}
Is there anyway in C++ to acheive a similar effect?
Under the hood reference is equivalent to a constant pointer to some variable (compiler just gives you a syntax sugar of how to work with such pointers so that they are always initialized).
So you wan't to have the same variable and two different pointers to it, one of which will dereference to true and the other to false. That is obviously impossible.
The OOP -way to do it would be to pass not reference to boolean but some interface to your classes and use implementation that uses same boolean variable:
class IIsOpenProvider
{
public:
virtual ~IIsOpenProvider() = 0;
virtual bool GetOpenValue() = 0;
};
class IIsClosedProvider
{
public:
virtual ~IIsClosedProvider() = 0;
virtual bool GetClosedValue() = 0;
};
class ValueProvider : public IIsOpenProvider, public IIsClosedProvider
{
public:
bool GetOpenValue() override { return isOpen; }
bool GetClosedValue() override { return !isOpen; }
private:
bool isOpen;
};
class A {
IIsOpenProvider& isOpen;
A(IIsOpenProvider& value): isOpen(value) {}
void f() {
if (isOpen.GetOpenValue()) {
doSomething();
}
}
};
class B {
IIsClosedProvider& isClosed;
B(IIsClosedProvider& value): isClosed(value) {}
void g() {
if (IIsClosedProvider.GetClosedValue()) {
doSomething();
}
}
};
// usage
ValueProvider val;
A a(val);
B b(val);
I need to create a queue of different class objects (These classes are not related). I found a solution as follows:
Create a base class and use polymorphism.
Here is how I implemented it,
class Task {
public:
virtual void operator()() {
printf("should not be called\n");
}
};
class TaskRPCB : public Task {
private:
int x;
// other varibles
std::function<void(int)> func;
public:
TaskRPCB(std::function<void(int)>&f , int x) {
this->func = f;
this->x = x;
}
void operator()() {
printf("TaskRPCB function is executing...\n");
func(x);
}
};
class TaskECB : public Task {
private:
// other varibles
std::function<void(void)> func;
public:
TaskECB(std::function<void(void)>&f) : func(f) {}
void operator()() {
printf("TaskECB function is executing...\n");
func();
}
};
void F1() { // dummy function for example
cout <<"no x"<<endl;
}
void F2(int x) { // dummy function for example
cout <<"x : "<<x<<endl;
}
int main() {
queue<unique_ptr<Task>> Q;
function<void()> func1 = F1;
function<void(int)> func2 = F2;
TaskECB task1(func1);
TaskRPCB task2(func2,4);
Q.emplace(new TaskECB(func1));
Q.emplace(new TaskRPCB(func2,4));
(*Q.front())();
Q.pop();
(*Q.front())();
Q.pop();
}
The problem is, I can not push the objects directly as shown above. I have to create an object of an inherited class and pass it to another function to do the push action. It is because ( in my case ) the queue is a part of a thread-safe queue and it has separate Push() method.
template<typename T>
void threadSafeQueue<T>::Push(T newData) { /* TODO: size check before pushing */
std::shared_ptr<T> data(std::make_shared<T>(std::move(newData)));
/* construct the object before lock*/
std::lock_guard<std::mutex> lk(mut);
taskQueue.push(data);
dataCond.notify_one();
}
Earlier I did not have multiple tasks to execute ( or push ) into the queue, therefore
threadSafeQueue<TaskRPCB> workQ declaration worked fine for me.
Creating a base Task class like above is not working because of object slicing
Can you suggest other ways to store objects in the queue ( so that I can still use the lock guarded Push() method )
Thanks !
update :
is the correct way of using variant?
typedef std::variant<TaskECB, TaskRPCB> myType;
int main() {
queue<unique_ptr<myType>> Q;
function<void()> func1 = F1;
function<void(int)> func2 = F2;
TaskECB task1(func1);
TaskRPCB task2(func2,4);
myType x = task1;
Q.push(make_unique<myType>(x));
x = task2;
Q.push(make_unique<myType>(x));
if((*Q.front()).index() == 0) {
auto f1 = get<TaskECB>(*Q.front());
f1();
Q.pop();
}
if((*Q.front()).index() == 1) {
auto f1 = get<TaskRPCB>(*Q.front());
f1();
Q.pop();
}
}
update2:
using myVariantType = std::variant<TaskECB, TaskRPCB>;
struct VisitPackage {
void operator()(TaskECB & task) {
task();
}
void operator()(TaskRPCB& task) {
task();
}
};
int main() {
queue<myVariantType> Q;
function<void()> func1 = F1;
function<void(int)> func2 = F2;
TaskECB task1(func1);
TaskRPCB task2(func2,4);
Q.emplace(task1);
Q.emplace(task2);
std::visit(VisitPackage(), Q.front());
Q.pop();
std::visit(VisitPackage(), Q.front());
Q.pop();
}
Just like passing class type as argument to method I want to pass enum, as I want to write a general method which operates on enum.
I tried:
void foo(E):
print(E.values[0])
but it doesn't work.
Is there a way?
This might work for you
typedef EnumValues<T> = List<T> Function();
void main() {
foo<E1>(() => E1.values);
foo<E2>(() => E2.values);
}
enum E1 { a, b }
enum E2 { c, d }
void foo<T>(EnumValues<T> valuesFn) {
var values = valuesFn();
for (var v in values) {
print(v);
}
}
See comments - shorter version
void main() {
foo<E1>(E1.values);
foo<E2>(E2.values);
}
enum E1 { a, b }
enum E2 { c, d }
void foo<T>(List<T> values) {
for (var v in values) {
print(v);
}
print(values[0]);
}
I am trying to create a function that will insert a node to the back of the list using linked list. I am new to using linked list and I have tried many different ways of doing an insertion at the end of the list but nothing seems to be working. The main passes the values one at a time to be inserted 2 4 5 8 9, and the output is 2 0 0 0 0. I do not whats causing this problem.
.h
class Node
{
public:
Node() : data(0), ptrToNext(NULL) {}
Node(int theData, Node *newPtrToNext) : data(theData), ptrToNext(newPtrToNext){}
Node* getPtrToNext() const { return ptrToNext; }
int getData() const { return data; }
void setData(int theData) { data = theData; }
void setPtrToNext(Node *newPtrToNext) { ptrToNext = newPtrToNext; }
~Node(){}
private:
int data;
Node *ptrToNext; //pointer that points to next node
};
class AnyList
{
public:
AnyList();
//default constructor
void print() const;
//Prints all values in the list.
void destroyList();
//Destroys all nodes in the list.
~AnyList();
//destructor
int getNumOfItems();
void insertBack(int b);
void deleteFirstNode();
private:
Node *ptrToFirst; //pointer to point to the first node in the list
int count; //keeps track of number of nodes in the list
};
.cpp
void AnyList::insertBack(int b)
{
Node *temp = new Node;
if (ptrToFirst == NULL)
{
temp->setData(b);
ptrToFirst = temp;
}
else
{
Node *first = ptrToFirst;
while (first->getPtrToNext() != NULL)
{
first = first->getPtrToNext();
}
first->setPtrToNext(temp);
}
}
First, you really should be using the std::list or std::forward_list class instead of implementing the node handling manually:
#include <list>
class AnyList
{
public:
void print() const;
//Prints all values in the list.
void destroyList();
//Destroys all nodes in the list.
int getNumOfItems() const;
void insertBack(int b);
void deleteFirstNode();
private:
std::list<int> nodes; //nodes in the list
};
void AnyList::print() const
{
for (std::list<int>::const_iterator iter = nodes.begin(); iter != nodes.end(); ++iter)
{
int value = *iter;
// print value as needed...
}
}
void AnyList::destroyList()
{
nodes.clear();
}
void AnyList::getNumOfItems() const
{
return nodes.size();
}
void AnyList::insertBack(int b)
{
nodes.push_back(b);
}
void AnyList::deleteFirstNode()
{
if (!nodes.empty())
nodes.pop_front();
}
That being said, your manual implementation fails because you are likely not managing the nodes correctly (but you did not show everything you are doing). It should look something like this:
class Node
{
public:
Node() : data(0), ptrToNext(NULL) {}
Node(int theData, Node *newPtrToNext) : data(theData), ptrToNext(newPtrToNext) {}
~Node() {}
Node* getPtrToNext() const { return ptrToNext; }
int getData() const { return data; }
void setData(int theData) { data = theData; }
void setPtrToNext(Node *newPtrToNext) { ptrToNext = newPtrToNext; }
private:
int data;
Node *ptrToNext; //pointer that points to next node
};
class AnyList
{
public:
AnyList();
//default constructor
~AnyList();
//destructor
void print() const;
//Prints all values in the list.
void destroyList();
//Destroys all nodes in the list.
int getNumOfItems() const;
void insertBack(int b);
void deleteFirstNode();
private:
Node *ptrToFirst; //pointer to point to the first node in the list
Node *ptrToLast; //pointer to point to the last node in the list
int count; //keeps track of number of nodes in the list
};
AnyList:AnyList()
: ptrToFirst(NULL), ptrToLast(NULL), count(0)
{
}
void AnyList::print() const
{
for (Node *temp = ptrToFirst; temp != NULL; temp = temp->getPtrToNext())
{
int value = temp->getData();
// print value as needed...
}
}
AnyList::~AnyList()
{
destroyList();
}
void AnyList::destroyList()
{
Node *temp = ptrToFirst;
ptrToFirst = ptrToLast = NULL;
count = 0;
while (temp != NULL)
{
Node *next = temp->getPtrToNext();
delete temp;
temp = next;
}
}
int AnyList::getNumOfItems() const
{
return count;
}
void AnyList::insertBack(int b)
{
Node *temp = new Node(b, NULL);
if (ptrToFirst == NULL)
ptrToFirst = temp;
if (ptrToLast != NULL)
ptrToLast->setPtrToNext(temp);
ptrToLast = temp;
++count;
}
void AnyList::deleteFirstNode()
{
if (ptrToFirst == NULL)
return;
Node *temp = ptrToFirst;
ptrToFirst = temp->getPtrToNext();
if (ptrToLast == temp)
ptrToLast = NULL;
delete temp;
--count;
}