I am working on implementing a generic stack data strucuture using STL and boost library.
#include <iostream>
#include <cstdio>
#include <stack>
#include <boost/any.hpp>
#include <boost/type_index.hpp>
using namespace std;
class Stack{
private:
std::stack<boost::any> st;
public:
bool empty();
int size();
boost::any top();
void push(boost::any ele);
void pop();
};
bool Stack::empty(){
return st.empty();
}
int Stack::size(){
return st.size();
}
boost::any Stack::top(){
return st.top();
}
void Stack::push(boost::any e){
st.push(e);
}
void Stack::pop(){
st.pop();
}
int main(){
Stack st;
int a = 10;
st.push(a);
int b = boost::any_cast<int>(st.top());
float c = 10.0;
st.push(c);
}
Although it's working perfectly but I want to avoid explicit typecast while retrieving an item from the stack. I want that somehow stack should return item after typecasting it automatically based on the item's type.
I am planning to maintain a hashmap with the stack which could store type information of every element and could be used to type cast each item before returning it, but I am not able to write this as code. Please suggest me some possible ways.
You cannot automatically cast to the right type; then the return type of your top() function would depend on whatever happens at runtime. So, what return type would you give your top() function at compile time? The best you can do is something like
template <typename T>
T top()
{
return boost::any_cast<T>(stack.top());
}
Edit: As for your comment – no, you cannot use auto return type to get the behavior you hope, because the compiler will deduce what type auto represents at compile time – and it deduces what you return: a boost::any. Anything more specific can only be known at runtime.
Related
I implemented, based on the boost examples, a threadsafe queue-class in the shared memory. It works as expected for a simple producer/consumer model.
As a next step, I defined the interface IConcurrentIPCQueue which is implemented by the ConcurrentIPCQueue class. I need the interface so I can implement an adapter to the queue for another issue.
The only difference between my first version and the current one below is the following:
First version:
template <class T> class ConcurrentIPCQueue
now adding the information, that I want to implement the interface like this:
Current version:
`template <class T> class ConcurrentIPCQueue :public IConcurrentIPCQueue<T>`
results in a read access violation on the consumer side. On the producer side, I can easily push_back and pop_front data correctly on its own. But strangely on the consumer side, I cannot access the shared memory (although the pair from segment.find returns correctly an address and 1).
So the question is, why the version with implementing the interface makes a difference on the consumer side and results in this strange error. And how I can solve it?
To keep the example short, I present here a minimalistic model of the queue:
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/deque.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/thread/lock_guard.hpp>
#include <sstream>
namespace boost_ipc = boost::interprocess;
static char const *SHMEMNAME= "SHMEM";
static char const *SHQUEUENAME= "MYQUEUE";
template <class T> class IConcurrentIPCQueue
{
public:
virtual void push_back(T const & data) = 0;
virtual bool pop_front(T & data) = 0;
virtual unsigned int size() = 0;
};
template <class T> class ConcurrentIPCQueue :public IConcurrentIPCQueue<T>
{
public:
// allocator for allocating memory from the shared memory
typedef boost_ipc::allocator<T, boost_ipc::managed_shared_memory::segment_manager> ShmemAlloc;
typedef boost_ipc::interprocess_mutex IPC_Mutex;
typedef boost_ipc::interprocess_condition IPC_Cond;
typedef boost::lock_guard<IPC_Mutex> LockGuard;
ConcurrentIPCQueue(ShmemAlloc salloc) : mQueue_(salloc) { }
void push_back(T const & data)
{
{
LockGuard lock(mMutex_);
mQueue_.push_back(data);
}
mWait_.notify_one();
}
bool pop_front(T & data)
{
LockGuard lock(mMutex_);
if (mQueue_.empty())
return false;
data = mQueue_.front(); // return reference to first element
mQueue_.pop_front(); // remove the first element
return true;
}
unsigned int size()
{
LockGuard lock(mMutex_);
return mQueue_.size();
}
private:
boost_ipc::deque<T, ShmemAlloc> mQueue_;
IPC_Mutex mMutex_;
IPC_Cond mWait_;
};
typedef ConcurrentIPCQueue<char> myqueue;
void consumer()
{
boost_ipc::managed_shared_memory openedSegment(boost_ipc::open_only, SHMEMNAME);
myqueue*openedQueue = openedSegment.find<myqueue>(SHQUEUENAME).first;
char tmp;
while (openedQueue->pop_front(tmp)) {
std::cout << "Received " << tmp << "\n";
}
}
void producer() {
boost_ipc::shared_memory_object::remove(SHMEMNAME);
boost_ipc::managed_shared_memory mysegment(boost_ipc::create_only, SHMEMNAME, 131072);
myqueue::ShmemAlloc alloc(mysegment.get_segment_manager());
myqueue*myQueue = mysegment.construct<myqueue>(SHQUEUENAME)(alloc);
char mychar='A';
for (int i = 0; i < 10; ++i)
myQueue->push_back(mychar);
while (myQueue->size() > 0)
continue;
}
int main()
{
//producer(); // delete comment for creating producer process
consumer();
return 0;
}
UPDATE:
I could reproduce it with MSVC15.3 and Boost 1.64.
Turns out that the vtable pointers are the issue: they are different in each process, which leads to Undefined Behaviour as soon as you have runtime polymorphic types (std::is_polymorphic<T>).
It turns out the documentation forbids it clearly: Is it possible to store polymorphic class in shared memory?
I'm trying to make a class that can hold and later call functions. It stores the functions in a map along with a string that holds the name of the function.
I tried doing this on Linux with GCC and got the following error: "invalid conversion from void(*)() to void *" on the line functionsMap[nameOfFunction] = func;
Here's the entire program I have so far. It's not done yet, but I'm really curious as to why this would compile under Visual C++ and not GCC. If I'm doing something wrong or could be doing something better, please let me know. Thanks!
#include <iostream>
#include <map>
#include <string>
using namespace std;
class Dyn_Class{
private:
map<string, void *> functionsMap;
public:
Dyn_Class(){}
template<typename ReturnValue>
void add_func( string nameOfFunction, ReturnValue(*func)() ){
functionsMap[nameOfFunction] = func;
}
void remove_func( string nameOfFunction ){
}
Dyn_Class operator()(string nameOfFunction){
}
};
void print(void){
for(int index = 0; index < 9; index++){
cout << index << " ";
}
cout << endl;
}
int main(){
Dyn_Class functionsList;
functionsList.add_func("print", print);
return 0;
}
To have a map of pointers to function taking no arguments and returning void you need:
std::map<std::string, void(*)()> functionsMap;
There is no point making add_func a template as it will only work when instantiated with ReturnValue = void (unless you add a potentially unsafe cast to its implementation).
If your code compiles with Visual C++ it is because Visual C++ is being permissive.
You can pass that function as a parameter like this:
void add(void * f()){...}
How do you pass a function as a parameter in C?
Think on using std::function instead:
class Dyn_Class{
private:
map<string, function<void()> > functionsMap;
public:
Dyn_Class(){}
template<typename FUNC>
void add_func(const string& nameOfFunction, FUNC func){
functionsMap.insert(make_pair(nameOfFunction, func));
}
void remove_func(const string& nameOfFunction ){
}
void operator()(const string& nameOfFunction){
functionsMap[nameOfFunction]();
}
};
Benefits? Using "function", you could use your plain old function pointers, you can use functors or you can use lambda expressions instead:
DynClass dyn;
dyn.add("print", []() { printf("Say hi"; } );
I am constructing a template structure and I need some trick to do the following:
I have a singly and two dimensional linked list, and I need first construct every node with no data in them after that I have to fill them with the data from a file. So I need if(x == UNINITIALIZED OR NOT) since the data could be string, int and double. I couldn't find a common null initializer just for that if check. I hope there is a way to do this.
I tried if(x == NULL), if(x == 0), if(x == ""), if(x == void). None of them worked.
if your node represents one of the types specified, you could simply use a template, template specialization, or overloading.
If you only have those three types, you could create specialized initializer functions for the known types.
template <class T>
class CNode {
public:
CNode() {
Init(m_Value);
}
private:
T m_Value;
static void Init(T n) { n = 0; } // Default catch for types that can be set to 0/NULL
static void Init(bool b) { b = false; }
static void Init(string str) { str = ""; }
};
Of course there are also ways of specifying type specifics for templated functions, but I don't remember that offhand. I know Boost uses those, it would be a way of specifying additional methods of initialization outside of the original definition.
As far as I understand your problem, I think the following code shows possible and interesting solution which uses two Boost libraries: Optional and Tuple:
#include <cassert>
#include <algorithm>
#include <iterator>
#include <list>
#include <string>
#include <boost/optional.hpp>
#include <boost/tuple/tuple.hpp>
int main()
{
typedef boost::tuple<std::string, double, int> value_t;
typedef boost::optional<value_t> node_t;
std::list<node_t> nodes;
// first construct every node with no data in them
std::fill_n(std::inserter(nodes, nodes.begin()), 5, node_t());
// check all nodes have not been initialized yet, so they are in "null" state
auto it = nodes.cbegin();
while (it != nodes.cend())
{
assert(!it->is_initialized());
++it;
}
// add non-null initialized node
// or fill with the data from a file, etc.
node_t n("abc");
nodes.insert(it, n);
assert(nodes.back().is_initialized());
}
I have some (library API, so I can't change the function prototype) function which is written the following way:
void FreeContext(Context c);
Now, at some moment of my execution I have Context* local_context; variable and this is also not a subject to change.
I wish to use boost::bind with FreeContext function, but I need to retrieve Context from local variable Context*.
If I write my code the following way, the compiler says it's "illegal indirection":
boost::bind(::FreeContext, *_1);
I managed to solve this problem the following way:
template <typename T> T retranslate_parameter(T* t) {
return *t;
}
boost::bind(::FreeContext,
boost::bind(retranslate_parameter<Context>, _1));
But this solution doesn't seem really good to me. Any ideas on how to solve this using something like *_1. Maybe writing a small lambda function?
You could use Boost.Lambda which have overloaded the * operator for _n.
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <algorithm>
#include <cstdio>
typedef int Context;
void FreeContext(Context c) {
printf("%d\n", c);
}
int main() {
using boost::lambda::bind;
using boost::lambda::_1;
Context x = 5;
Context y = 6;
Context* p[] = {&x, &y};
std::for_each(p, p+2, bind(FreeContext, *_1));
return 0;
}
Use either Boost.Lambda or Boost.Phoenix to have a working operator* on a placeholder.
You can also place the Context pointer in a shared_ptr with a custom deleter:
#include <memory> // shared_ptr
typedef int Context;
void FreeContext(Context c)
{
printf("%d\n", c);
}
int main()
{
Context x = 5;
Context* local_context = &x;
std::shared_ptr<Context> context(local_context,
[](Context* c) { FreeContext(*c); });
}
Not sure this is relevant though. Good luck!
Out of curiosity, I thought I'd try and write a basic C++ class that mimics C#'s multiple delegate pattern. The code below mostly does the job, with the nasty sacrifice of losing almost all type-safety, but having to use the initial dummy parameter to set up the va_list really seems a bit off. Is there a way to use va_list without this?
I do realize there are ways to do this with (for example) boost, but I was aiming for something dead simple that used just the standard library.
#include <vector>
#include <iostream>
#include <string>
#include <stdarg.h>
#include <algorithm>
using namespace std;
class CDelegate
{
public:
virtual bool operator()(va_list params) = 0;
};
class CMultipleDelegateCaller
{
public:
typedef vector<CDelegate*> CDelegateVector;
CMultipleDelegateCaller& operator+=(CDelegate &rDelegate)
{
m_apDelegates.push_back(&rDelegate);
return (*this);
}
CMultipleDelegateCaller& operator-=(CDelegate &rDelegate)
{
CDelegateVector::iterator iter =
find(m_apDelegates.begin(), m_apDelegates.end(), &rDelegate);
if (m_apDelegates.end() != iter) m_apDelegates.erase(iter);
return (*this);
}
bool Call(int iDummy, ...)
{
va_list params;
CDelegate* pDelegate;
CDelegateVector::iterator iter;
for (iter = m_apDelegates.begin(); iter != m_apDelegates.end(); ++iter)
{
pDelegate = *iter;
va_start(params, iDummy);
if (!(*pDelegate)(params)) return false;
va_end(params);
}
return true;
}
private:
CDelegateVector m_apDelegates;
};
class CTestDelegate:
public CDelegate
{
public:
CTestDelegate():m_iId(++s_iCount) {}
virtual bool operator()(va_list params)
{
int iIntParam = va_arg(params, int);
char* szCharPtrParam = va_arg(params, char*);
string* psStringParam = va_arg(params, string*);
cout<<m_iId<<"{"
<<iIntParam<<", "
<<szCharPtrParam<<", "
<<*psStringParam<<"}"<<endl;
return true;
}
int m_iId;
static int s_iCount;
};
int CTestDelegate::s_iCount = 0;
int main(int argc, char* argv[])
{
CMultipleDelegateCaller cDelegateCaller;
CTestDelegate cTestDelegate1;
CTestDelegate cTestDelegate2;
cout<<"--------------------"<<endl;
cDelegateCaller += cTestDelegate1;
cDelegateCaller += cTestDelegate2;
string sString("World");
cDelegateCaller.Call(1, 2, "Hello", &sString);
cout<<"--------------------"<<endl;
cDelegateCaller -= cTestDelegate1;
cDelegateCaller.Call(1, 2, "Hello", &sString);
cout<<"--------------------"<<endl;
cDelegateCaller -= cTestDelegate2;
cDelegateCaller.Call(1, 2, "Hello", &sString);
cout<<"--------------------"<<endl;
cin>>sString;
return 0;
}
Functions with ellipsis in C++ is only for compatibility with C. Using C++ I'd return temporary helper object in Call function and add template operator% to pass variable number of arguments. To use it in the following way:
cDelegateCaller.Call() % 2 % "Hello" % sString; // dummy argument isn't required
As to your question, Standard requires to invoke va_start before any access to the unnamed arguments. And va_start requires second argument which is the identifier of the rightmost parameter in the variable parameter list in the function definition.
Out of Kirill's answer you can conclude that it's possible to create a type-safe delegate, using a template argument-combining function. This function also needs a dummy starting point, but has the benefit of type-safety.
The FastFormat library uses this, boost uses this, and I once provided another example in an answer to another question.