Predicate syntax when partitioning a vector of pointers (C++) - predicate

I have a vector of pointers to objects. I'd like to remove objects from this vector according to an attribute that's reported by a member function.
I'm trying to follow a nice example I found on how to delete certain pointers (and their associated objects) from the vector. The basic idea is to partition the vector, delete the chosen objects, and then delete the pointers to those objects. Below is the example (from Dr. Dobbs):
vector<Object *> v ;
v.push_back( new Object( ... ) ) ;
...
vector<Object *>::iterator last =
partition( v.begin(), v.end(), not1(predicate()) ) ;
for( vector<Object *>::iterator i = last ; i != v.end() ; ++i )
{
delete *i ;
}
v.erase( last, v.end() ) ;
I'm stumped on the proper syntax for the predicate. My objects are of class Strain, and my vector is vector< Strain * > liveStrains. The predicate should be the Strain member function isExtinct(). The following doesn't work:
vector< Strain * >::iterator last = partition( liveStrains.begin(), liveStrains.end(), not1(std::mem_fun_ref(&Strain::isExtinct)) );
I can see that I am trying to invoke a member function on a pointer to the object rather than the object itself. To get around this, tried changing the & to * (I'm obviously a newbie), and I tried creating a member function for the class Simulation that does the liveStrains updating in a member function. I'm not sure it's worth going into the details of what didn't work. I'm severely confused by the syntactical options available, or if what I'm trying to do is even allowed.
Thanks in advance for any help.

The solution is to use std::mem_fun, which is made for pointers to objects, rather than std::mem_fun_ref.

Related

Dynamic logical expression evaluating

I need to evaluate a dynamic logical expression and I know that in ABAP it is not possible.
I found the class cl_java_script and with this class I could achieve my requeriment. I've try something like this:
result = cl_java_script=>create( )->evaluate( `( 1 + 2 + 3 ) == 6 ;` ).
After the method evaluate execution result = true as espected. But my happiness is over when I look into the class documentation that says This class is obsolete.
My question is, there is another way to achieve this?
Using any turing complete language to parse a "dynamic logical expression" is a terrible idea, as an attacker might be able to run any program inside your expression, i.e. while(true) { } will crash your variant using cl_java_script. Also although I don't know the details of cl_java_script, I assume it launches a separate JS runtime in a separate thread somewhere, this does not seem to be the most efficient choice to calculate such a small dynamic expression.
Instead you could implement your own small parser. This has the advantage that you can limit what it supports to the bare minimum whilst being able to extend it to everything you need in your usecase. Here's a small example using reverse polish notation which is able to correctly evaluate the expression you've shown (using RPN simplifies parsing a lot, though for sure one can also build a full fledged expression parser):
REPORT z_expr_parser.
TYPES:
BEGIN OF multi_value,
integer TYPE REF TO i,
boolean TYPE REF TO bool,
END OF multi_value.
CLASS lcl_rpn_parser DEFINITION.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING
text TYPE string,
parse
RETURNING VALUE(result) TYPE multi_value.
PRIVATE SECTION.
DATA:
tokens TYPE STANDARD TABLE OF string,
stack TYPE STANDARD TABLE OF multi_value.
METHODS pop_int
RETURNING VALUE(result) TYPE i.
METHODS pop_bool
RETURNING VALUE(result) TYPE abap_bool.
ENDCLASS.
CLASS lcl_rpn_parser IMPLEMENTATION.
METHOD constructor.
" a most simple lexer:
SPLIT text AT ' ' INTO TABLE tokens.
ASSERT lines( tokens ) > 0.
ENDMETHOD.
METHOD pop_int.
DATA(peek) = stack[ lines( stack ) ].
ASSERT peek-integer IS BOUND.
result = peek-integer->*.
DELETE stack INDEX lines( stack ).
ENDMETHOD.
METHOD pop_bool.
DATA(peek) = stack[ lines( stack ) ].
ASSERT peek-boolean IS BOUND.
result = peek-boolean->*.
DELETE stack INDEX lines( stack ).
ENDMETHOD.
METHOD parse.
LOOP AT tokens INTO DATA(token).
IF token = '='.
DATA(comparison) = xsdbool( pop_int( ) = pop_int( ) ).
APPEND VALUE #( boolean = NEW #( comparison ) ) TO stack.
ELSEIF token = '+'.
DATA(addition) = pop_int( ) + pop_int( ).
APPEND VALUE #( integer = NEW #( addition ) ) TO stack.
ELSE.
" assumption: token is integer
DATA value TYPE i.
value = token.
APPEND VALUE #( integer = NEW #( value ) ) TO stack.
ENDIF.
ENDLOOP.
ASSERT lines( stack ) = 1.
result = stack[ 1 ].
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
" 1 + 2 + 3 = 6 in RPN:
DATA(program) = |1 2 3 + + 6 =|.
DATA(parser) = NEW lcl_rpn_parser( program ).
DATA(result) = parser->parse( ).
ASSERT result-boolean IS BOUND.
ASSERT result-boolean->* = abap_true.
SAPs BRF is an option, but potentially massive overkill in your scenario.
Here is a blog on calling BRF from abap.
And here is how Rules/Expressions can be defined dynamically.
BUT, if you know enough about the source problem to generate
1 + 2 + 3 = 6
Then it is hard to imagine why a simple custom parser cant be used.
Just how complex should the expressions be ?
Id probably write my own parser before investing in calling BRF.
Since some/many BSPs use server side JAVAscript and not ABAP as the scripting language, i cant see SAP removing the Kernel routine anytime soon.
SYSTEM-CALL JAVA SCRIPT EVALUATE.
SO maybe consider Just calling the cl_java_script anyway until it is an issue.
Then worry about a parser if and when it is really no longer a valid call.
But definitely some movement in the obsolete space here.
SAP is pushing/forcing you to cloud with the SDK, to execute such things.
https://sap.github.io/cloud-sdk/docs/js/overview-cloud-sdk-for-javascript

Populating a std::vector map using the operator[]?

Am I overcomplicating this? Since I recently learned that with std::vector you can use the [] operator and it will add the entry if missing.
I have something a little more detailed:
using WeekendFutureItemHistMap = std::map<CString, std::vector<COleDateTime>>;
using WeekendFutureHistMap = std::map<WeekendHistAssign, WeekendFutureItemHistMap>;
WeekendHistAssign is just an enum class.
In my function I am populating it this way:
if (m_mapScheduleFutureHist[eHistAssign].find(strName) != m_mapScheduleFutureHist[eHistAssign].end())
m_mapScheduleFutureHist[eHistAssign][strName].push_back(datAssign);
else
{
m_mapScheduleFutureHist[eHistAssign].emplace(strName, std::vector<COleDateTime>{datAssign});
}
According to the std::vector operator[] it states:
Returns a reference to the element at specified location pos. No bounds checking is performed.
As a result it seemed the right thing to do is test for the existing first as done.
Did I overcomplicate it?
std::vector<int> v;
v.resize(100);
v[0]=1;
v[1]=10;
...

moving objects in NSMutableArray without changing array size

I have a 'MutableArray' that I want to edit by moving different objects in it up and down the index via the method shown here: NSMutablearray move object from index to index.
My problem is that Xcode first takes care of the 'removeObjectAtIndex' method before the 'insertObject:atIndex:' so the array actually shrinks in size which makes certain transitions impossible. An example would be if my 'array' has 3 members and I change the third member's index from 2 to 2 so nothing should happen but actually the app crashes because after the removal the index bound is now [0,1].
Below is the code I am using to implement the move in array, I also get a Parse Issue: Expected identifier error from the compiler at the 'if' statement right behind the queue.count. Any help on both would be much appreciated.
-(void)makeRankChange:(NSMutableArray *)queue{
for (int queueCount =0; queueCount<queue.count; queueCount++) {
QueueMember *member = [queue objectAtIndex:queueCount];
if (member.rank != queueCount+1) {
if ([0<member.rank] && [member.rank < [queue.count(expected identifier here:Im not sure why)]]) {
[queue insertObject:member atIndex:member.rank-1];
[queue removeObjectAtIndex:queueCount];
}
}
}
}
How about replacing the value at the index:
[queue replaceObjectAtIndex:queueCount withObject:member];
The error is most likely from the '[' brackets in the if statement

Design a data structure for reporting resource conflicts

I have a memory address pool with 1024 addresses. There are 16 threads running inside a program which access these memory locations doing either read or write operations. The output of this program is in the form of a series of quadruples whose defn is like this
Quadruple q1 : (Thread no, Memory address, read/write , time)
e.g q1 = (12,578,r,2t), q2= (16,578,w,6t)
I want to design a program which takes the stream of quadruples as input and reports all the conflicts which occur if more than 2 threads try to access the same memory resource inside an interval of 5t secs with at least one write operation.
I have several solutions in mind but I am not sure if they are the best ones to address this problem. I am looking for a solution from a design and data structure perspective.
So the basic problem here is collision detection. I would generally look for a solution where elements are added to some kind of associative collection. As a new element is about to be added, you need to be able to tell whether the collection already contains a similar element, indicating a collision. Here you would seem to need a collection type that allows for duplicate elements, such as the STL multimap. The Quadraple (quadruple?) would obviously be the value type in the associative collection, and the key type would contain the data necessary to determine whether two elements represent a collision, i.e. memory address and time. In order to use a standard associative collection like STL multimap, you need to define some ordering on the keys by defining operator< for the key type (I'm assuming C++ here, you didn't specify). You define a collision as two elements where the memory location is identical and the time values differ by less than some threshold amount. The ordering of the key type has to be such that two keys that represent a collision come out as equivalent under the ordering. Equivalence under the < operator is expressed as a < b is false and b < a is false as well, so the ordering might be defined by this operator:
bool operator<( Key const& a, Key const& b ) {
if ( a.address == b.address ) {
if ( abs(a.time - b.time) < threshold ) {
return false;
}
return a.time < b.time;
}
return a.address < b.address;
}
There is a problem with this design, due to the fact that two keys may be equivalent under < without being equal. This means that two different but similar Quadraples, i.e. two values that collide with one another, would be stored under the same key in the collection. You could use a simpler definition of the ordering
bool operator<( Key const& a, Key const& b ) {
if ( a.address == b.address ) {
return a.time < b.time;
}
return a.address < b.address;
}
Under this ordering definition, colliding elements end up adjacent in an ordered associative container (but under different keys), so you'd be able to find them easily in a post-processing step after they have all been added to the collection.

Visual C++ hash_multimap not finding any results

I need some help understanding how stdext::hash_multimap's lower_bound, upper_bound and equal_range work (at least the VS2005 version of it).
I have the following code (summarized for the question)
#include <hash_map>
using stdext::hash_multimap;
using std::greater;
using stdext::hash_compare;
using std::pair;
using std::cout;
typedef hash_multimap < double, CComBSTR, hash_compare< double, greater<double> > > HMM;
HMM hm1;
HMM :: const_iterator it1, it2;
pair<HMM::const_iterator, HMM::const_iterator> pairHMM;
typedef pair <double, CComBSTR> PairDblStr;
// inserting only two values for sample
hm1.insert ( PairDblStr ( 0.224015748, L"#1-64" ) );
hm1.insert ( PairDblStr ( 0.215354331, L"#1-72" ) );
// Using a double value in between the inserted key values to find one of the elements in the map
it1 = hm1.lower_bound( 0.2175 );
if( it1 == hm1.end() )
{
cout << "lower_bound failed\n";
}
it1 = hm1.upper_bound( 0.2175 );
if( it1 == hm1.end() )
{
cout << "upper_bound failed\n";
}
pairHMM = hm1.equal_range( 0.2175 );
if( ( pairHMM.first == hm1.end() ) && ( pairHMM.second == hm1.end() ) )
{
cout << "equal_range failed\n";
}
As mentioned in the comment I am passing in a value (0.2175) that is in between the two inserted key values (0.224015748, 0.215354331). But the output of the code is:
lower_bound failed
upper_bound failed
equal_range failed
Did I misunderstand how the lower_bound, upper_bound and equal_range can be used in maps? Can we not find a "closest match" key using these methods? If these methods are not suitable, would you have any suggestion on what I could use for my requirement?
Thanks in advance for any help.
Thanks to #billy-oneal #dauphic for their comments and edits. I have updated the code above to make it compilable and runnable (once you include the correct headers of course).
Can we not find a "closest match" key using these methods?
No. hash_multimap is implemented using a hashtable. Two keys that are very close to each other (0.2153 and 0.2175, for example) will likely map to totally different bins in the hashtable.
A hashtable does not maintain its elements in a sorted order, so you cannot find the closest match to a given key without a linear search.
The lower_bound, upper_bound, and equal_range functions in hash_multimap have a somewhat odd implementation in the Visual C++ standard library extensions.
Consider the documentation for lower_bound:
The member function determines the first element X in the controlled sequence that hashes to the same bucket as key and has equivalent ordering to key. If no such element exists, it returns hash_map::end; otherwise it returns an iterator that designates X. You use it to locate the beginning of a sequence of elements currently in the controlled sequence that match a specified key.
And the documentation for upper_bound:
The member function determines the last element X in the controlled sequence that hashes to the same bucket as key and has equivalent ordering to key. If no such element exists, or if X is the last element in the controlled sequence, it returns hash_map::end; otherwise it returns an iterator that designates the first element beyond X. You use it to locate the end of a sequence of elements currently in the controlled sequence that match a specified key.
Essentially, these functions allow you to identify the range of elements that have a given key. Their behavior is not the same as the behavior of std::lower_bound or std::map::lower_bound (theirs is the behavior that you were expecting).
For what it's worth, the C++0x unordered associative containers do not provide lower_bound, upper_bound, or equal_range functions.
Would you have any suggestion on what I could use for my requirement?
Yes: if you need the behavior of lower_bound and upper_bound, use an ordered associative container like std::multimap.

Resources