I have a object of type of Map<String^, Object^>^. How do I iterate in C++/CX way? I am trying to use iterator but I am not clear about syntax. Documentation doesn't provide an example.
C++/CX collections follow the same principles as c++ collections, so they have iterators and begin, end functions.
IMap<Platform::String^, Platform::Object^>^ map = ref new Map<Platform::String^, Platform::Object^>();
map->Insert("key1", "val1");
map->Insert("key2", 2.0f);
// Exactly like you would iterate over a map, but instead of std::pair you have IKeyValuePair
std::for_each(begin(map), end(map), [](IKeyValuePair<Platform::String^, Platform::Object^>^ pair)
{
// do stuff
auto key = pair->Key;
auto value = pair->Value;
});
for( auto pair : map )
{
// do stuff
auto key = pair->Key;
auto value = pair->Value;
}
Also, don't forget to include collection.h and use namespace Platform::Collections.
Related
I'm pretty much trying to make a AddInputEvent but, after a month, can't find a way to turn a local "function from FunctionCallbackInfo"(i'll just call this argf) in to a Persistent Function so that garbage collection doesn't erase the pointers.
Most stakeoverflow threads and example code I can find just say to Cast argf with a Local Function; then to throw that in to a Persistent New. This results in a error: cannot convert 'v8::Local<v8::Function>' to 'v8::Function*'
here is the code, not completely sure why I can't convert it
class inputevnt_feld{
public:
char* call_on;
v8::Persistent<v8::Function> func;
};
int entvcount = -1;
vector<inputevnt_feld> event_calls; //this is pretty much a array of events that we can call later
// in js looks like this "AddInputEvent("string", function);"
void AddInputEvent( const v8::FunctionCallbackInfo<v8::Value>& args ) {
v8::HandleScope handle_scope(args.GetIsolate());
//gotta make sure that we ain't letting in some trojan horse that has nothing in it
if (args[1]->IsFunction() && args[0]->IsString()) {
inputevnt_feld newt;
//converts js string to char array
v8::String::Utf8Value str(args.GetIsolate(), args[0]);
const char* cstr = ToCString(str);
newt.call_on = (char*)cstr;
//here is where the problem is with function casting
v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[1]);
newt.func = v8::Persistent<v8::Function>::New(args.GetIsolate(), callback);
//push the new stuff in to even array
event_calls.push_back(newt);
//getting vector array size is too much for my smol brain
//so I'ma just do this myself
entvcount++;
//cout << event_calls[entvcount].call_on << endl; //debug
}
}
Most stakeoverflow threads and example code I can find just say to Cast argf with a Local Function; then to throw that in to a Persistent New
Yes, that's correct. If you know how to read it, the C++ type system is your friend for figuring out the details.
If you look at the definition of v8::PersistentBase<T>::New, you'll see that it takes a T* (for its template type T). If you look at the v8::Local<T> class, you'll see that a way to get a T* from it is to use its operator*. That leads to:
v8::Local<v8::Function> callback = ...Cast(args[1]);
... = v8::Persistent<v8::Function>::New(..., *callback);
Alternatively, you can use the Persistent constructor directly, and pass it the Local without dereferencing it first:
v8::Local<v8::Function> callback = ...Cast(args[1]);
... = v8::Persistent<v8::Function>(..., callback);
Both options are entirely equivalent. Personally I'd prefer the latter as it takes slightly fewer characters to spell out, but that's really the only difference.
(Your current code as posted does something else: it ignores the result of the cast and passes the original args[1] directly to Persistent::New -- that's not going to work.)
I don't understand the constructor statement in the following code. How can the iterator to the past-of-end element be added to the map as a key?
template<typename K, typename V>
class my_map {
std::map<K,V> m_map;
public:
my_map( V const& val) {
m_map.insert(m_map.end(),std::make_pair(std::numeric_limits<K>::lowest(),val));
}
};
How can the iterator to the past-of-end element be added to the map as a key?
It's not the key. It's the position of the insertion. By passing end you're saying append to the map.
The key that you're inserting is the first part of the pair. i.e. std::numeric_limits<K>::lowest().
The value that you're inserting is the second part of the pair. i.e. val.
The docs for std::map::insert are useful.
How can the iterator to the past-of-end element be added to the map as a key?
That's an incorrect conclusion. std::map::insert has several overloads. The one that is use in your call is:
iterator insert( iterator hint, const value_type& value ); // Overload 4
which does the following:
Inserts value in the position as close as possible, just prior, to hint.
for example :
set<set<T>> outer_set;
set<T> insider_set1, insider_set2;
T a;
insider_set1.insert(a);
outer_set.insert(insider_set1);
outer_set.insert(insider_set2);
set<T>::iterator chosen_itr;
for(auto temp_set: outer_set){
if(temp_set.count(a)){
chosen_itr = temp_set.begin();
break;
}
}
T b = something(...);
*chosen_itr.insert(b);
will this code add b to the insider_set1 inside of outer_set or the chosen_itr belongs to a temporary set that was created at
auto temp_set
if chosen_itr is some random iterator how to get the real one??
As you point out in your question, you're keeping a pointer (iterator) into a temporary. You should use a reference instead:
for(auto& temp_set: outer_set){
Then the given code would be valid, with one more simple change:
chosen_itr->insert(b);
1. > iterator of a set inside a set is equal to the insider set.begin()?
no it insider_set1.begin() will point to the first element in the insider_set
to get an iterator (pointer) to the set it self the for(auto set1: outsider_sit) cant be used instead, which i was trying to avoid, is to use
for(auto itr = outsider_set.begin(); ire != outsider_set.end(); ++itr)
and then save the itr value at the chosen set.
2. will this work ?
no the itr iterator to a set> is an iterator to a constant, sets is immutable in c++ and the values inside a set can not be changed after being add even if those values are containers.
3. how to add b to a set inside the outsider_set ??
sense we cant change the values inside the set we have to remove the old value(insider_set) and insert a new value(insider_set) after being updated like so:
set<set<T>> outer_set;
set<T> insider_set1, insider_set2;
T a;
insider_set1.insert(a);
outer_set.insert(insider_set1);
outer_set.insert(insider_set2);
set<T> chosen_set;
set<T>::iterator chosen_itr; // not needed now
for(auto temp_set: outer_set){
if(temp_set.count(a)){
//chosen_itr = temp_set.begin(); // not working
chosen_set = temp_set;
break;
}
}
T b = something(...);
outsider_set.erase(chosen_set);
chosen_set.insert(b)
outsider_set.insert(chosen_set);
this solution may not be efficient but I think is the only way, besides using const_cast to insert, if any have better one please mention it.
I've seen ways of using HTML Helpers and such to deal with enums in MVC. I've taken a different approach in that I pass a string[] of the checked boxes back to the controller. I am doing this:
foreach (string svf in property.SiteVisibilityFlags)
{
Enums.SiteVisibilityFlags flagTester;
if (Enum.TryParse<Enums.SiteVisibilityFlags>(svf, out flagTester))
{
// add to domainProperty
domainProperty.SiteVisibilityFlags = flagTester; <--Here is where I mean
}
}
Now, I know that normally, with a flagged enum you do something like:
domainProperty.SiteVisibilityFlags = Enums.SiteVisibilityFlags.Corporate | Enums.SiteVisibilityFlags.Properties;
So, if/how can I accomplish the '|'... in this methodology?
You could use the [FlagAttribute] explained here.
From there you can simply use the bit-or (|) operator as follows
domainProperty.SiteVisibilityFlags |= flagTester;
Also there is a really good explanation with examples on stackoverflow about attribute
figured it out. Any enum that has [Flags] as an attribute can be solved by summing up the values of all checked items like this:
// Site Visibility Flags
int SiteVisibilityTotalValue = 0;
foreach (string svf in property.SiteVisibilityFlags)
{
Enums.SiteVisibilityFlags flagTester;
if (Enum.TryParse<Enums.SiteVisibilityFlags>(svf, out flagTester))
{
// sum up values to get total to them convert to enum
SiteVisibilityTotalValue += (int)flagTester;
}
}
// convert total to Enum
domainProperty.SiteVisibilityFlags = (Enums.SiteVisibilityFlags)SiteVisibilityTotalValue;
I would like to implement this functionality in an embedded JavaScript application that uses v8 engine.
function myFunction1() {
//do stuff
}
function myFunction2() {
//do other stuff
}
myAddon.addCallback(myFunction1);
myAddon.addCallback(myFunction2);
myAddon.removeCallback(myFunction1);
In order to do this I need to store these functions in a std::set like so
void addCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::HandleScope scope(args.GetIsolate());
v8::Local<v8::Function> cb = v8::Local<v8::Function>::Cast(args[0]);
std::set mySet = this->mySet;
//now how do I insert a reference to this function into mySet so I can retrieve
//it later
}
void removeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::HandleScope scope(args.GetIsolate());
v8::Local<v8::Function> cb = v8::Local<v8::Function>::Cast(args[0]);
std::set mySet = this->mySet;
//now how do I remove the element in this set that refers to this function?
}
How does one go about doing this? I don't want to use v8::Object::GetIdentityHash() because the result is not guaranteed to be unique.
I also can't just store the Local in the std::set because the copy constructor is private and it would also get descoped once removeCallback or addCallback return.
Thanks for any help in advance.
Edit: I realize I could write some javascript to do the function hashing for me, and then call one C++ binded function to iteration through all the callbacks, but I'd rather not do this every time I need to store sets or hashes of JavaScript objects.
This is correct that you can't safely store Local<T> handle, because when it gets out of scope, your function object may become available to garbage collection. What you need is a persistent handle. You can construct it out of local like:
v8::Local<v8::Function> cb = v8::Local<v8::Function>::Cast(args[0]);
v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>> value(isolate, cb);
Note CopyablePersistentTraits which allows handle copying. There is also NonCopyablePersistentTraits if you would like to prevent that.
Now you can put it in a vector:
std::vector<v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>>> v;
v.push_back(value);
Convert back to local:
v8::Local<v8::Function> local = v8::Local<v8::Function>::New(isolate, value);
For std::set you also need to provide comparison function for elements. It also might be a good idea to wrap v8::Persistent<T> into your own class like PersistentWrapper<T> (this is what I am doing in my project) to get the desired behavior.