How to use vectors (of C++ STL) with WebAssembly - c++14

#include <iostream>
#include<vector>
using namespace std;
vector<int> ver;
int pushData(int n)
{
for(int i=0;i<n;i++)
{
ver.push_back(i);
}
}
I want to call pushData function from JS and push some data to vector "ver" and use it later.
please explain how to do that using WebAssembly.

i'm do something like you.In my opinion, using STL in WASM is very difficult.
My solution is to create a simulate vector.Wasm only supports int32, int64, float32 and float64 and wasm's adderess is differnt from other process.So it is not feasible to import the library directly. You can call the library function through a proxy or conversion.Or you can write it by yourself.
In this case, vector can't be imported directly.You can create a class named vector,and implement the push_back function.
class vector{
public:
bool push_back(int i){
// do something
}
int& at(uint index){
// do something
}
private:
int* int_ptr;
}
More details here
https://aransentin.github.io/cwasm/

Related

Is that possible to have a for loop in compile time with runtime or even compile time limit condition in c++11?

I would like to know if it is possible to have a for loop in compile time with runtime or even compile time limit condition in c++11?
I start with a silly try to find out what I need.
for (uint32_t i = 0; i < n; ++i)
{
templated_func<i>();
}
consider I have a class with a private member variable n, and I want to call a template function with a different number that iterates from 0 to n (for the case of runtime limit condition)
I've had studies on the "Template Metaprogramming" and "Constexpr If" (c++17) but I have not gotten any results, can anyone help me?
You can't have a for loop, but you can call N lots of templated_func
namespace detail {
template <template<uint32_t> class F, uint32_t... Is>
void static_for_impl(std::integer_sequence<uint32_t, Is...>)
{
F<Is>{}()...;
}
}
template <template<uint32_t> class F, uint32_t N>
void static_for()
{
detail::static_for_impl<F>(std::make_integer_sequence<uint32_t, N>{});
}
template <uint32_t I>
struct templated_caller
{
void operator()() { templated_func<I>(); }
}
int main()
{
static_for<templated_caller, 10>();
return 0;
}
Note that this is more general than what you asked for. You can simplify it to just
template <uint32_t... Is>
void call_templated_func(std::integer_sequence<uint32_t, Is...>)
{
templated_func<Is>()...;
}
int main()
{
call_templated_func(std::make_integer_sequence<uint32_t, N>{});
return 0;
}
but that's lengthy to repeat multiple times, and you can't pass a function template as a template parameter.
As you said you only had C++11 then you will not have std::make_index_sequence and will have to provide it. Also, the fold expression in Caleth's answer is not available until C++17.
Providing your own implementation of index_sequence and a fold expression in c++11 can be done in the following way,
#include <iostream>
template <size_t... Is>
struct index_sequence{};
namespace detail {
template <size_t I,size_t...Is>
struct make_index_sequence_impl : make_index_sequence_impl<I-1,I-1,Is...> {};
template <size_t...Is>
struct make_index_sequence_impl<0,Is...>
{
using type = index_sequence<Is...>;
};
}
template<size_t N>
using make_index_sequence = typename detail::make_index_sequence_impl<N>::type;
template<size_t I>
void templated_func()
{
std::cout << "templated_func" << I << std::endl;
}
template <size_t... Is>
void call_templated_func(index_sequence< Is...>)
{
using do_ = int[];
do_ {0,(templated_func<Is>(),0)...,0};
}
int main()
{
call_templated_func(make_index_sequence< 10>());
return 0;
}
This is essentially the same as the answer by #Caleth , but with the missing bits provided and will compile on c++11.
demo
demo on c++11 compiler
I would like to know if it is possible to have a for loop in compile time with runtime or even compile time limit condition in c++11
I don't know a reasonable way to have such loop with a runtime condition.
With a compile time condition... If you can use at least C++14, you can use a solution based on std::integer_sequence/std::make_integer_sequence (see Caleth answer) or maybe std::index_sequence/std::make_index_sequence (just a little more synthetic).
If you're limited with C++11, you can create a surrogate for std::index_sequence/std::make_index_sequence or you can create a recursive template struct with static function (unfortunately you can partially specialize a template function but you can partially specialize classes and structs).
I mean... something as follows
template <std::size_t I, std::size_t Top>
struct for_loop
{
static void func ()
{
templated_func<I>();
for_loop<I+1u, Top>::func();
}
};
template <std::size_t I>
struct for_loop<I, I>
{ static void func () { } };
that you can call
constexpr auto n = 10u;
for_loop<0, n>::func();
if you want to call templated_func() with values from zero to n-1u.
Unfortunately this solution is recursive so you can have troubles with compilers recursion limits. That is... works only if n isn't high.

Static assert on size of static const member

I'm trying to put a static assert on the size of static const unordered_map member. But I get an error saying non-const condition for static assertion. Could someone help?
#include<unordered_map>
#include<string>
using namespace std;
class A{
public:
static const unordered_map<string,string> strMap;
};
const unordered_map<string,string> A::strMap ={{"key","value"}};
int main() {
static_assert(A::strMap.size() == 1, "sizes don't match");
}
EDIT: Based on the comments, I want to clarify, the following code works fine (it uses an array instead of a map):
#include<unordered_map>
#include<string>
using namespace std;
class A{
public:
static const pair<string,string> strMap[];
};
const pair<string,string> A::strMap[] ={{"key","value"}};
int main() {
//static_assert(sizeof(A::strMap)/sizeof(A::strMap[0]) == 2, "sizes don't match"); Fails to compile
static_assert(sizeof(A::strMap)/sizeof(A::strMap[0]) == 1, "sizes don't match"); //Compiles fine
}
Can't do this. You'd need constexpr std::unordered_map for this, and this is not possible, since it's constructor is not constexpr. And of course, no class which allocates memory (unordered_map being of this kind) can declare it's constructor constexpr.

c++11 template metaprogramming construct a std::unorderer_map at compile time

i trying to develop a Finite State Machine with template meta programming techniques, but i getting stuck with a map that it has to be fill at compile time, this the code(gcc 4.8 c++11):
#include <functional>
#include <type_traits>
#include <iostream>
#include <unordered_map>
namespace NSStateMachine {
//Definicion de estado unidad
template<class FSM, class From, class Event, class TO, bool(FSM::* transicion_fn)(const Event &)>
struct Transition
{
using FSM_TYPE=FSM;
using FROM_STATE= From;
using EVENT_TYPE= Event;
using TO_STATE_TYPE=TO;
using EVENT_BASE_TYPE = typename Event::BASE_TYPE;
static bool do_transition(FSM_TYPE& currenState, EVENT_BASE_TYPE const& aEvent)
{
return (currenState.*transicion_fn)(static_cast<EVENT_TYPE const&>(aEvent));
}
};
//States
template<class Transition, const Transition * const TransitionPtr, class ... Args>
class StateMachine
{
public:
StateMachine():transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
{}
template<class Event>
bool evalEvent(const Event & aEvent)
{
std::cout<<"evento recibido"<<std::endl;
}
std::unordered_map<typename Transition::TransitionID, const Transition * const > transitionMap ;
};
}
int main()
{
//it doesnt compile, i canoot create the state machine
return 0;
}
The compile error:
error: 'TransitionPtr' is not a class, namespace, or enumeration
StateMachine():transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
^
The problem seem to be in the line
transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
i will try to init the unorderer_map with the automatic constructor.
i have defined this Transition::TransitionID as a class variable defined in the class represented by the template argument
I will really appreciate any help.
Thx!!!!
i have already test with default types , it compile and work this
The error message is pretty clear. TransitionPtr is a pointer, not a type, so you can't use it to the left of :: in TransitionPtr::TransitionID_Value.
Also, I don't think you'll find a way to initialize an unordered_set at compile time, since it doesn't have constexpr constructors and in general almost certainly uses heap allocations.

How to construct vector in the vector by boost::interprocess

I have leraned the boost sample about "Create vectors in shared_memory".
Now My data structure is like :
Data structure:
enum FuncIndex
{
enmFunc_glBegin,
...
}
class CGLParam {};
class Funcall
{
vector<CGLParam> vecParams;
};
class Global_Funcall
{
typedef allocator<CGLParam*, managed_shared_memory::segment_manager> ShmemAllocator;
typedef vector<CGLParam*, ShmemAllocator> MyVector;
MyVector<FunCall> vecFuncalls;
};
Global_Funcall()
{
shared_memory_object::remove("MySharedMemory");
managed_shared_memory segment(create_only, "MySharedMemory", 65536);
//Initialize shared memory STL-compatible allocator
const ShmemAllocator alloc_inst(segment.get_segment_manager());
//Construct a vector named "MyVector" in shared memory with argument alloc_inst
vecFuncalls= segment.construct<MyVector>("MyVector")(alloc_inst);
}
void InvokeFuncs(CGLParam *presult)
{
managed_shared_memory open_segment(open_only,"MySharedMemory");
listParams = open_segment.find<MyVector>("MyVector").first;
// MyVector::const_iterator it;
// for (it = listParams->cbegin(); it != listParams->cend(); it++)
// {
// (*it)->InvokeFunc(presult);
// }
}
My problem is "How to construct the vecParams and how to get it". the size of data is very big (opengl function calls)
The structure is use to save the opengl function calls.
Besides 'obvious' typos, you try to assign an IPC vector (MyVector*) to a standard vector in the GlobalFuncall constructor. That will never work. C++ is a strongly typed language, so the types have to match if you want to assign[1].
Besides this there seems to be a conceptual problem:
if the goal is to have a data collection that could be larger than fits in phyical memory, shared-memory per se isn't going to help. You'd want to look at memory-mapped files
if you want shared-memory because you can share it between processes (hence Boost Interprocess), you will need to think of process synchronization, or you will see complicated bugs because of data races.
you cannot safely store raw pointers inside this containers. Instead, store the actual elements there (or maybe look at bip::offset_ptr<> if you want to get really fancy).
Here's a 'fixed up' demonstration
fixing the C++ compilation issues,
changing the element type to be CGLParam instead of CGLParam*
fixing the member type to match the SHM vector and
adding basic shared mutex synchronization (this is an art in itself and you will want to read more about this)
See it Live On Coliru[1]
#include <vector>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/named_recursive_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
namespace bip = boost::interprocess;
using mutex_type = bip::named_mutex;
class CGLParam {};
typedef bip::allocator<CGLParam, bip::managed_shared_memory::segment_manager> ShmemAllocator;
typedef std::vector<CGLParam, ShmemAllocator> MyVector;
class Funcall
{
std::vector<CGLParam> vecParams;
};
struct mutex_remove
{
mutex_remove() { mutex_type::remove("2faa9c3f-4cc0-49c5-8f79-f99ce5a5d526"); }
~mutex_remove(){ mutex_type::remove("2faa9c3f-4cc0-49c5-8f79-f99ce5a5d526"); }
} remover;
static mutex_type mutex(bip::open_or_create,"2faa9c3f-4cc0-49c5-8f79-f99ce5a5d526");
class Global_Funcall
{
MyVector* vecFuncalls;
Global_Funcall()
{
bip::scoped_lock<mutex_type> lock(mutex);
bip::shared_memory_object::remove("MySharedMemory");
bip::managed_shared_memory segment(bip::create_only, "MySharedMemory", 65536);
//Initialize shared memory STL-compatible allocator
const ShmemAllocator alloc_inst(segment.get_segment_manager());
//Construct a vector named "MyVector" in shared memory with argument alloc_inst
vecFuncalls = segment.construct<MyVector>("MyVector")(alloc_inst);
}
};
void InvokeFuncs(CGLParam *presult)
{
bip::scoped_lock<mutex_type> lock(mutex);
bip::managed_shared_memory open_segment(bip::open_only, "MySharedMemory");
auto listParams = open_segment.find<MyVector>("MyVector").first;
MyVector::const_iterator it;
for (it = listParams->cbegin(); it != listParams->cend(); it++)
{
//it->InvokeFunc(presult);
}
}
int main()
{
}
[1] Unless, of course, there's a suitable conversion
[2] Coliru doesn't support the required IPC mechanisms :/

Why is Visual Studio using std::iterator<> instead of mine::iterator<>

I've been trying to figure out this problem for a couple days now and finally figured it out after striping everything down to the code below. You'll see in the code below three different attempts at a constructor for const_iterator, along with the errors I get on two of them. It appears to me that the compiler is trying to use std::iterator instead of the locally declared mine::iterator. Is it supposed to be that way?
Other tidbits that have given clues:
If I name mine::iterator something else, like mine::B, then const_iterator(const B &rhs) works.
If I derive const_iterator from a class other than std::iterator, then const_iterator(const iterator<T> &rhs) works.
Thanks for any info. Here's the code:
#include "stdafx.h"
#include <iterator>
namespace mine
{
template <class T>
class iterator : public std::iterator<std::random_access_iterator_tag, T, ptrdiff_t, T*, T&>
{
public:
iterator() {}
};
template <class T>
class const_iterator : public std::iterator<std::random_access_iterator_tag, T, ptrdiff_t, const T*, const T&>
{
public:
const_iterator() {}
const_iterator(const mine::iterator<T> &rhs) {} // works
//const_iterator(const iterator &rhs) {} // error C2440: initializing: cannot convert from 'mine::iterator<T>' to 'mine::const_iterator<T>'
//const_iterator(const iterator<T> &rhs) {} // error C2976: std::iterator: too few template arguments
};
}// namespace mine
using namespace mine;
int _tmain(int argc, _TCHAR* argv[])
{
iterator<int> y;
const_iterator<int> x = y;
return 0;
}
First of all 'using namespace' is evil, use typedef for ease of use. for example instead of saying iterator use mine::iterator.
Also your second point gives the answer of your question. "If I derive const_iterator from a class other than std::iterator, then const_iterator(const iterator<T> &rhs) works."
Here the nearest iterator belongs to std not mine, as std::iterator is the base class of your const_iterator.

Resources