Proper implementation of removing vector elements - c++

ALL,
It's continuation of this thread.
What I tried is to write following code:
struct Remover : public std::binary_function<CPlayer,void,bool>
{
public:
bool operator()(const CPlayer &player) const
{
return player.IsNewPlayer();
}
};
and call it this way:
players_pool->erase( std::remove_if( players_pool->begin(), players_pool->end(), std::bind2nd( Remover() ) ) );
but it gives me an error:
std::bind2nd(): expects 2 arguments - 1 provided.
How do I properly call this functor?
Thank you.

You don't need to wrap Remover() in std::bind2nd().
Also, you don't need to derive from std::binary_function<> (which is wrong, anyway; Remover is a unary functor). You don't need to derive from anything, in fact.
Finally, if your compiler supports C++11, you can reduce your code down to this:
players_pool->erase( std::remove_if( begin(*players_pool), end(*players_pool),
[](const CPlayer &player) {
return player.IsNewPlayer();
} ),
end(*players_pool) );

Just change your binary_function to a unary_function.
You also need to add the end iterator to the erase call, in order to erase all removed values.

Related

C++ CppCheck algorithm suggestion (std::find_if instead of raw loop) pertinence

CppCheck suggest me to replace one of my code by a STL algorithm, I'm not against it, but I don't know how to replace it. I'm pretty sure this is a bad suggestion (There is warning about experimental functionalities in CppCheck).
Here is the code :
/* Cutted beginning of the function ... */
for ( const auto & program : m_programs )
{
if ( program->compare(vertexShader, tesselationControlShader, tesselationEvaluationShader, geometryShader, fragmentShader) )
{
TraceInfo(Classname, "A program has been found matching every shaders.");
return program;
}
}
return nullptr;
} /* End of the function */
And near the if condition I got : "Consider using std::find_if algorithm instead of a raw loop."
I tried to use it, but I can't get the return working anymore... Should I ignore this suggestion ?
I suppose you may need to use that finding function not once. So, according to DRY, you need to separate the block where you invoke an std::find_if algorithm to a distinct wrapper function.
{
// ... function beginning
auto found = std::find_if(m_programs.cbegin(), m_programs.cend(),
[&](const auto& prog)
{
bool b = prog->compare(...);
if (b)
TraceInfo(...);
return b;
});
if (found == m_programs.cend())
return nullptr;
return *found;
}
The suggestion is good. An STL algorithm migth be able to choose an appropriate
approach based on your container type.
Furthermore, I suggest you to use a self-balancing container like an std::set.
// I don't know what kind of a pointer you use.
using pProgType = std::shared_pointer<ProgType>;
bool compare_progs(const pProgType &a, const pProgType &b)
{
return std::less(*a, *b);
}
std::set<std::shared_pointer<prog_type>,
std::integral_constant<decltype(&compare_progs), &compare_progs>> progs.
This is a sorted container, so you will spend less time for searching a program by a value, given you implement a compare operator (which is invoked by std::less).
If you can use an stl function, use it. This way you will not have to remember what you invented, because stl is properly documented and safe to use.

In C++17 can an if statement with an initializer be used to unpack an optional?

I'm writing some code using std::optional's and am wondering if C++17's 'if statements with initializers' will be able to help unpack values?
std::optional<int> optionalInt = GetOptionalInt();
I'm making up the function Unpack here:
if( auto [value, has_value] = optionalInt.Unpack(); has_value )
{
// Use value here.
}
But, my question is. Will C++17 'if statement with initializer' help here? If so, how would it be coded?
Update, this is actually mainly an issue when using optional which is extremely easy to misuse because the optional and *optional both return bools and you don't get any compiler warning when somebody trys to access the value and forgets the *.
There is not, and cannot possibly be, such an Unpack() function.
But you could certainly do:
if (std::optional<int> o = GetOptionalInt(); o) {
// use *o here
}
though the extra o check is kind of redundant.
This is one of those places where it'd be nice if optional<T> modeled a container of at most one element, so that you could do:
for (int value : GetOptionalInt()) {
// possibly not entered
}
but we don't have that interface.
In order for this to work, there has to be a value for the unpacked value if it isn't there.
So
template<class T, class U>
std::pair< T, bool > unpack_value( std::optional<T> const& o, U&& u ) {
return { o.value_or(std::forward<U>(u)), (bool)o } )
}
would do what you wanted.
But as an optional already returns if it is engaged in a bool context you really should just:
if (auto i = get_optional())
then use *i within the body.
...
Now if optional stated that operator* returned a reference, and that return value was defined but accessing it was not defined when it was not engaged, then you could write an Unpack method or function that doesn't require a default value.
As far as I am aware this is not true. And as it doesn't really add anything, I don't see why it should be true.
Maybe this would work:
auto optValue = getOptional();
if (auto value = *optValue; optValue) { ...use value here... }

Is there a better way to do a find with optional insert using unordered_map of objects with no default constructor?

I have the following code:
class CEvent
{
public:
CEvent(std::string const&) {}
};
std::unordered_map<std::string, CEvent> m_messageList;
CEvent& GetMessageEvent(std::string const& name)
{
auto it = m_messageList.find(name);
if (it == m_messageList.end())
{
auto pair = m_messageList.emplace(std::piecewise_construct,
std::forward_as_tuple(name), // Copy-construct 'name' as the key
std::forward_as_tuple(name)); // Construct CEvent in-place with the name
return pair.first->second;
}
return it->second;
}
(Live Sample)
I think the code is pretty clean, but I don't like that I have to do a find separate from emplace. Is there a way to do this better? Or is this "good enough"? I know I could probably call emplace instead of find first, to accomplish both tasks, but this means creating a CEvent every time, even if no real insert happens.
Once C++17 is released (or if your compiler supports prerelease versions),
return m_messageList.try_emplace(name, name).first; should do the trick.

Boost::multi_index with map

I have a question about modifying elements in boost::multi_index container.
What I have is the structure, containing some pre-defined parameters and
a number of parameters, which are defined at run-time, and stored in a map.
Here is a simplified version of the structure:
class Sdata{
QMap<ParamName, Param> params; // parameters defined at run-time
public:
int num;
QString key;
// more pre-defined parameters
// methods to modify the map
// as an example - mock version of a function to add the parameter
// there are more functions operating on the QMAP<...>, which follow the same
// rule - return true if they operated successfully, false otherwise.
bool add_param(ParamName name, Param value){
if (params.contains(name)) return false;
params.insert(name, value);
return true;
}
};
Now, I want to iterate over different combinations of the pre-defined parameters
of Sdata. To do this, I went for boost::multi_index:
typedef multi_index_container<Sdata,
indexed_by <
// by insertion order
random_access<>,
//by key
hashed_unique<
tag<sdata_tags::byKey>,
const_mem_fun<Sdata, SdataKey, &Sdata::get_key>
>,
//by TS
ordered_non_unique<
tag<sdata_tags::byTS>,
const_mem_fun<Sdata, TS, &Sdata::get_ts>
>,
/// more keys and composite-keys
>//end indexed by
> SdataDB;
And now, I want to access and modify the parameters inside the QMap<...>.
Q1 Do I get it correctly that to modify any field (even those unrelated to
the index), one needs to use functors and do something as below?
Sdatas_byKey const &l = sdatas.get<sdata_tags::byKey>();
auto it = l.find(key);
l.modify(it, Functor(...))
Q2 How to get the result of the method using the functor? I.e., I have a functor:
struct SdataRemoveParam : public std::unary_function<Sdata, void>{
ParamName name;
SdataRemoveParam(ParamName h): name(h){}
void operator ()(Sdata &sdata){
sdata.remove_param (name); // this returns false if there is no param
}
};
How to know if the remove_param returned true or false in this example:
Sdatas_byKey const &l = sdatas.get<sdata_tags::byKey>();
auto it = l.find(key);
l.modify(it, SdataRemoveParam("myname"));
What I've arrived to so far is to throw an exception, so that the modify
method of boost::multi_index, when using with Rollback functor will return
false:
struct SdataRemoveParam : public std::unary_function<Sdata, void>{
ParamName name;
SdataRemoveParam(ParamName h): name(h){}
void operator ()(Sdata &sdata){
if (!sdata.remove_param (name)) throw std::exception("Remove failed");
}
};
// in some other place
Sdatas_byKey const &l = sdatas.get<sdata_tags::byKey>();
auto it = l.find(key);
bool res = l.modify(it, SdataRemoveParam("myname"), Rollback);
However, I do not like the decision, because it increases the risk of deleting
the entry from the container.
Q3 are there any better solutions?
Q1 Do I get it correctly that to modify any field (even those
unrelated to the index), one needs to use functors and do something as
below?
Short answer is yes, use modify for safety. If you're absolutely sure that the data you modify does not belong to any index, then you can get by with an ugly cast:
const_cast<Sdata&>(*it).remove_param("myname");
but this is strongly discouraged. With C++11 (which you seem to be using), you can use lambdas rather than cumbersome user-defined functors:
Sdatas_byKey &l = sdatas.get<sdata_tags::byKey>(); // note, this can't be const
auto it = l.find(key);
l.modify(it, [](Sdata& s){
s.remove_param("myname");
});
Q2 How to get the result of the method using the functor?
Again, with lambdas this is very simple:
bool res;
l.modify(it, [&](Sdata& s){
res=s.remove_param("myname");
});
With functors you can do the same but it requires more boilerplate (basically, have SdataRemoveParam store a pointer to res).
The following is just for fun: if you're using C++14 you can encapsulate the whole idiom very tersely like this (C++11 would be slightly harder):
template<typename Index,typename Iterator,typename F>
auto modify_inner_result(Index& i,Iterator it,F f)
{
decltype(f(std::declval<typename Index::value_type&>())) res;
i.modify(it,[&](auto& x){res=f(x);});
return res;
}
...
bool res=modify_inner_result(l,it, [&](Sdata& s){
return s.remove_param("myname");
});

removing duplicates from a c++ list

I have been looking for an effective solution to remove duplicates from a C++ list.
The list consists of pointers to a class object which has an attribute ID. I want to remove duplicates based on that ID.
for my purpose, the unique method of the STL list will work in which we can pass a BinaryPredicate. i.e.
void unique( BinPred pr );
I searched on the internet about how to use this method, n got an example in which we can declare a function returning boolean and use the "name" of that function as Binary Predicate.
But it's not working.
What actually is this binary predicate and how do i use it ? ...
Any help will be appreciated.
Here is the code snippet:
class SP_MDI_View {
..
..
bool removeDupli(SP_DS_Node*, SP_DS_Node*);
bool DoReductionGSPN(SP_DS_Node*, SP_ListNode*, SP_DS_Node*);
..
..
}
SP_MDI_View::DoReduction( ... ) {
SP_ListNode setZ; // typedef list<SP_DS_Node*> SP_ListNode, where SP_DS_Node is some other class
setZ.clear();
setZ.merge(tempsubset);
setZ.merge(setX);
setZ.push_back(*cs_iter);
setZ.unique(removeDupli); //Error here
}
bool SP_MDI_View::removeDupli(SP_DS_Node* first, SP_DS_Node* second) {
return ( (first->GetId())==(second->GetId()) );
}
You could write a function like:
bool foo (int first, int second)
{ return (first)==(second) ); }
Also, you might need to declare the function as static if your using it in class.
You have to use unique on an ordered list. So the first thing that you must do is sort the list.