I have an unordered_set of a class ActiveStatusEffect The set is declared as follows:
boost::unordered_set<StatusEffects::ActiveStatusEffect> ActiveStatusEffects;
ActiveStatusEffect is defined as follows:
class ActiveStatusEffect
{
public:
StatusEffect* effect;
int ReminaingTurns;
bool operator<(const ActiveStatusEffect& ase) const
{
return *effect < *ase.effect;
}
bool operator>(const ActiveStatusEffect& ase) const
{
return *effect > *ase.effect;
}
bool operator==(const ActiveStatusEffect& ase) const
{
return *effect == *ase.effect;
}
bool operator!=(const ActiveStatusEffect& ase) const
{
return !((*this) == ase);
}
};
The comparison between StatusEffect's is a comparison between a unique integer assinged to each instance of a status effect.
However, if I try to sort the effects like follows:
std::sort(statusSet.begin(), statusSet.end(), [](StatusEffects::ActiveStatusEffect const &se1, StatusEffects::ActiveStatusEffect const &se2){return se1.effect->GetPriority() < se2.effect->GetPriority();});
I get many errors in the algorithm header file such as
Error 198 error C2784:
'_Base1::difference_type std::operator
-(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2>
&)' : could not deduce template
argument for 'const
std::_Revranit<_RanIt,_Base> &' from
'boost::unordered_detail::hash_const_iterator' c:\program
files (x86)\microsoft visual studio
10.0\vc\include\algorithm 3806
Error 199 error C2784:
'_Base1::difference_type std::operator
-(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2>
&)' : could not deduce template
argument for 'const
std::_Revranit<_RanIt,_Base> &' from
'boost::unordered_detail::hash_const_iterator' c:\program
files (x86)\microsoft visual studio
10.0\vc\include\algorithm 3806
Why am I not able to sort the set? I'm quite certain this is something about unordered_set as removing attempts to sort or changing it to a vector does not generate errors.
unordered_set doesn't have non-const iterators, because if you could mutate the item pointed to by an iterator you could violate the invariants of the set (uniqueness among others). Additionally if you sorted an unordered_set you would no longer be able to look up the item in the container anymore (assuming it works by hash).
If you really want to sort the set of items, you'll need to copy it into a vector first and then sort that. But in that case have you considered if unordered_set is the right container for you in the first place? What about using a normal set which is ordered at the expense of lookups being slower.
boost::unordered_set<Foo> a;
a.insert(...);
...
std::set<Foo> b(a.begin(), a.end());
std::set<Foo> c;
std::copy(a.begin(), a.end(), std::inserter(c, c.end());
VoilĂ , a sorted set.
I am facing an error while trying to add a reference of object to vector of pointers:
template <class Tpoint, class Tmodel> Tmodel ransac<Tpoint, Tmodel>::perform_fitting(const std::vector<Tpoint>& data){
std::vector<Tpoint*> also_inliers;
for (const auto& pnt : data){
if (fit_point(pnt, may_be_model) <= t){
also_inliers.push_back(&pnt); //error here
}
} // ! for range
}
Error message from VS.NET 2013:
Error 88 error C2664: 'void std::vector>::push_back(cv::Point_ *const &)' : cannot convert argument 1 from 'const cv::Point_ *' to
'cv::Point_ *&&'
You capture pnt as const auto&, but you then try to push it into a vector containing non-const pointers. This violates const-correctness.
Either change also_inliers to std::vector<const Tpoint*> if you aren't going to be modifying those pointee objects or capture by auto& if you need the modification.
have a
std::list<MyBaseClass*> objects;
how ( mean a syntax) would you specialize std::greater
for the sort method of std::list
template<> class std::greater<MyBaseClass*> {
public:
bool operator()(const MyBaseClass*& lhs, const MyBaseClass*& rhs) const
{
return lhs->get_index() > rhs->get_index();
}
produces the error:
C2662: 'int MyBaseClass::get_index(void)' : cannot convert 'this' pointer from 'const MyBaseClass' to 'MyBaseClass &'
Conversion loses qualifiers
can you explain me the problem please?
Your implementation of eidos::MyBaseClass::get_index() needs to be marked as "const".
I have a function template that takes a vector and an element of a given type and returns the position of the element in the vector. This is the code for this function template:
template<class T>
int findElement(const vector<T> &vec, const T &ele)
{
for(size_t i = 0; i < vec.size(); i++)
{
if(ele == vec[i])
return i;
}
return -1;
}
And here's the function call:
findElement<double>(intVec, ele);
But I get this error when I call the function:
error C2664: 'findElement' : cannot convert parameter 1 from 'std::vector<_Ty>' to 'const std::vector<_Ty,_Ax> &'
And this error is same even if I remove the const for the vector in the function template definition:
error C2664: 'findElement' : cannot convert parameter 1 from 'std::vector<_Ty>' to 'std::vector<_Ty,_Ax> &'
However, when I make the function call as
findElement(intVec, ele)
I do not get any error.
What is the reason for this behavior?
Seems like compiler cannot convert vector<double> to vector<int>. Since by logic way, intVec is vector of ints, isn't it? And you say compiler, that you want vector of doubles.
You cannot convert vector<T> to vector<U>, since vector has no following conversion constructor, and it's nice.
I'm trying to get the includes algorithm to work on a set and map by comparing the map's keys to the set's values. The issue that needs to be circumvented is of course that map<K,V>::value_type is pair<K,V> while set<V>::value_type is V so these are not going to work with the default includes predicate<T> which expects the same value type for both arguments.
I am hence writing the below predicate classes to get around this
template <class P,class K>
struct mapKey_set_less : public std::binary_function<P,K,bool>
{
inline bool operator() (const P& x, const K& y) const {return x.first < y ;};
};
template <class K,class P>
struct set_mapKey_less : public std::binary_function<K,P,bool>
{
inline bool operator() (const K& x, const P& y) const {return x < y.first ;};
};
However the template instantiator is throwing up on line 313 of the VS2008 xutility file
if (!_Pred(_Left, _Right))
with the message that it cannot convert parameter 1 from const V to const std::pair<_Ty1,_Ty2>
This seems to be caused by line 3795 of the file
if (_DEBUG_LT_PRED(_Pred, *_First2, *_First1))
where the first and second arguments seem to have been swapped
Compiling in Release Configuration gives the same error on line 3795, so it seems the Visual Studio implementation wants you to go through this code unless you tinker with whatever switch (if any) removes this '_DEBUG_LT_PRED' macro.
My question is:
Is this a bug in Visual Studio or is there a reason for this to be this way and I am making a mistake? I haven't done any C++ in over a decade and had to pick up last week to get some speed ups in some tight loops so need all the help I can get.
Thanks all
Nice,
I didn't think about the requirements of the algo. Makes sense it needs to check "less than" from both sides.
Not getting much joy getting this to compile though.
With my previous code of
template <class P,class K>
struct mapKey_set_cmp //: public std::binary_function<P,K,bool>
{
inline bool operator() (const P& x, const K& y) const {return x.first < y ;};
};
I was getting
error C2664: 'bool mapKey_set_cmp<P,K>::operator ()(const P &,const K &) const' :
cannot convert parameter 1 from 'const double' to 'const std::pair<_Ty1,_Ty2> &'
which makes sense as there is no operator() that can take a double as its 1st argument.
With the additional overloaded operator()
template <class P,class K>
struct mapKey_set_cmp //: public std::binary_function<P,K,bool>
{
inline bool operator() (const P& x, const K& y) const {return x.first < y ;};
inline bool operator() (const K& x, const P& y) const {return x < y.first ;};
};
I am now getting
error C2664: 'bool mapKey_set_cmp<P,K>::operator ()(const K &,const P &) const' :
cannot convert parameter 1 from 'const std::pair<_Ty1,_Ty2>' to 'const double &'
error C2664: 'bool mapKey_set_cmp<P,K>::operator ()(const K &,const P &) const' :
cannot convert parameter 1 from 'const std::pair<_Ty1,_Ty2>' to 'const double &'
error C2664: 'bool mapKey_set_cmp<P,K>::operator ()(const K &,const P &) const' :
cannot convert parameter 2 from 'const double' to 'const std::pair<_Ty1,_Ty2> &'
error C2664: 'bool mapKey_set_cmp<P,K>::operator ()(const K &,const P &) const' :
cannot convert parameter 2 from 'const double' to 'const std::pair<_Ty1,_Ty2> &'
Of note is that all the errors seem to reffer to the 2nd operator(), the one with the K 1st and P 2nd. And yes, none of the conversions mentioned should be possible on that operator. But why isn't the compiler trying the other operator? ie the one on which those conversions should be allowed. (BTW the errors are repeated because they each occur on two different lines in case you are wondering)
Another thing this could be is of course const incorrectness. It's been a while so I'll try to think that through.
Thanks for the help
Edit on 15 May 2013
I had to "get on with it" so circumvented this problem by puting my map Keys into a set so that I could call the includes algo on two sets (incurring the obvious performance penalty). I would still like to solve this properly though. Here is all the code neded to replicate the compiler error I am describing with Visual Studio 2008
template <class PAIR,class KEY>
struct mapKey_set_less : public std::binary_function<PAIR,KEY,bool>
{
inline bool operator() (const PAIR& x, const KEY& y) const {return x.first < y ;};
inline bool operator() (const KEY& x, const PAIR& y) const {return x < y.first ;};
};
int _tmain(int argc, _TCHAR* argv[])
{
map<string,double> theMap;
theMap["arse"] = 1;
set<string> theSet;
theSet.insert("arse");
typedef map<string,double>::iterator MI;
MI mi(theMap.begin()), miend(theMap.end());
typedef set<string>::iterator SI;
SI si(theSet.begin()), siend(theSet.end());
typedef mapKey_set_less< pair<string,double>,string> cmp;
if (includes(mi,miend,si,siend,cmp()))
{}
}
The compiler spits out
Error 1 error C2664: 'bool mapKey_set_less<PAIR,KEY>::operator ()(const KEY &,const PAIR &) const' : cannot convert parameter 1 from 'std::pair<_Ty1,_Ty2>' to 'const std::string &' c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility 346
Error 2 error C2664: 'bool mapKey_set_less<PAIR,KEY>::operator ()(const KEY &,const PAIR &) const' : cannot convert parameter 1 from 'std::pair<_Ty1,_Ty2>' to 'const std::string &' c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility 348
Error 3 error C2664: 'bool mapKey_set_less<PAIR,KEY>::operator ()(const KEY &,const PAIR &) const' : cannot convert parameter 2 from 'std::basic_string<_Elem,_Traits,_Ax>' to 'const std::pair<_Ty1,_Ty2> &' c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility 346
Error 4 error C2664: 'bool mapKey_set_less<PAIR,KEY>::operator ()(const KEY &,const PAIR &) const' : cannot convert parameter 2 from 'std::basic_string<_Elem,_Traits,_Ax>' to 'const std::pair<_Ty1,_Ty2> &' c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility 348
Looking at the 1st error alone it seems that it wants to use the operator()(KEY,PAIR) to pass in PAIR,KEY. Why is it ignoring the available operator()(PAIR,KEY)???
The other errors are all in the same vein, the compiler "appears" to ignore a perfectly good overloaded operator
Thanks all for the help
There is no requirement from the standard that objects from the first range will only be passed as the left hand argument of the comparison function, nor that objects in the second range will only be passed as the right hand argument. So, what Visual Studio is doing is perfectly valid, and often necessary (see below).
What you can do is write a single functor that handles both cases:
template <class K,class P>
struct set_mapKey_less : public std::binary_function<K,P,bool>
{
inline bool operator() (const K& x, const P& y) const {return x < y.first;};
inline bool operator() (const P& y, const K& x) const {return y.first < x; }
};
...
std::map<int,int> m;
std::set<int> s;
std::includes(m.begin(), m.end(), s.begin(), s.end(),
set_mapKey_less<int,std::pair<int const,int> >());
To understand why the check that VS is doing might be necessary, consider the following:
set X = { 1000, 3000, 5000, 7000, 9000 }
map Y = { (3000,'a') }
How are you going to test whether X includes Y if all you have is an less than operator that takes a pair value on the left, and an integer on the right?
Is (3000,'a').first < 1000? No.
Is (3000,'a').first < 3000? No.
Is (3000,'a').first < 5000? Yes.
At this point, we know that (3000,'a').first, if in the set, has to be 3000. But how do we test that it actually is 3000 with a comparator that can only take the pair on the left side? If we can reverse the arguments, we can do it:
Is 3000 < (3000,'a').first? No.
So now we know that 3000 is not less than (3000,'a').first, and (3000,'a').first is not less than 3000, therefore they must be equal.