For the life of me, I cannot get this code to work. I'm attempting to convert my code from C# to C++ following the deprecation of the XNA framework, but a stubborn method does not want to be converted. In C# it is:
public Tile GetTileAtPosition(bool screenOrGame, Vector2 position)
{
if (screenOrGame)
{
return Array.Find(tileList, tile => tile.Position == position / 24);
}
else
{
return Array.Find(tileList, tile => tile.Position == position);
}
}
In C++, the code I'm attempting to use in place of this is:
Tile Level::GetTileAtPosition(bool screenOrGame, sf::Vector2f position)
{
vector<Tile>::iterator it;
if (screenOrGame)
{
it = find(tileList.begin(), tileList.end(), [position](const Tile &t) { return t.GetPosition() == sf::Vector2f(position.x / 24, position.y / 24); });
return Tile(it->GetID(), it->GetPosition().x, it->GetPosition().y);
}
else
{
it = find(tileList.begin(), tileList.end(), [position](const Tile& t) { return t.GetPosition() == position; });
return Tile(it->GetID(), it->GetPosition().x, it->GetPosition().y);
}
}
On the C++ assignment lines (it = ...) I am getting a painstaking error that I cannot figure out the cause of, or a solution for. It returns:
error C2679: binary '==' : no operator found which takes a right-hand operand of type 'const Blobby::Level::GetTileAtPosition::<lambda_29eb981cd341d9c05d39c4654bc470b9>' (or there is no acceptable conversion) c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility 3186
Is there any way to fix this error, or a better/more practical way to implement the method in C++?
In C++, the versions taking a comparator are sometimes suffixed with _if. This is the case for std::find. std::find takes an element to find, whereas std::find_if takes a comparator that implements equality. The error simply means that it couldn't find a match for a Tile being equivalent to a lambda.
Related
I'm writing some intersection code for a Ray tracer. After calculating some intersection logic for a sphere, I want to return an optional to determine if there was an intersection or not. Instead of returning an "invalid" value for distance, I want to use C++'s std::optional class. The only issue is that it seems to always return true for has_value():
std::optional<Intersection> Sphere::ray_intersection(Ray ray)
// Calculate Intersection Logic
// ...
if (distance_to_intersection < 0) {
return std::nullopt;
} else {
return Intersection(ray, distance_to_intersection);
}
}
After returning, I check using the following code:
if (sphere.ray_intersection(ray).has_value()) {
return shade(sphere, intersection);
} else {
return background_color;
}
I know the actual intersection logic works correctly, because when I replace return std::nullopt; with return Intersection(ray, -1); (an invalid distance) and then simply check if the distance is equal to -1 in the previous if check, it behaves as expected.
I've also tried returning a simple {} to no avail.
I'm currently using Microsoft Visual Studio 2022, and I have tried both the C++17 and C++20 compilers, and neither will behave as I'm expecting.
Is there a specific way that std::optional operates that I'm not aware of?
I try to compile the following code:
class CFileOperations
{
...
template <typename T>
inline void load_and_save_data(std::fstream* stream, T& value, const EOperation operation)
{
switch (operation) {
case EOperation::OpSave:
*stream << value; <-- here
break;
case EOperation::OpLoad:
*stream >> value; <-- and here
break;
}
}
...
};
I get the following errors:
Error C2679 binary '<<': no operator found which takes a right-hand operand of type 'T' (or there is no acceptable conversion)
Error C2679 binary '>>': no operator found which takes a right-hand operand of type 'T' (or there is no acceptable conversion)
For example, I use it this way, with number being an 'int':
this->load_and_save_data(stream, number, operation);
I'm using Visual C++ 2019.
What's the root cause, and how to solve it. Any idea ?
My bad, one of the calls was with a 'class enum'. Of course, >> and << are not defined for it.
For #cdhowie, here are two examples of the resulting simplicity (with the help of load_and_save_data template methods):
Here mMembers is a std::unorderedmap (cf. save_and_load_data in the question above, I have also one for the starndard containers):
void CHexArea::load_and_save()
{
this->load_and_save_data((char&)mColor);
this->load_and_save_data(mTouchLeft);
this->load_and_save_data(mTouchRight);
this->load_and_save_data(mTouchBottom);
this->load_and_save_data(mTouchTop);
this->load_and_save_data(mMembers);
}
Here, in preferences, there are two versions of files:
void CHexPreferences::load_and_save()
{
if( this->is_loading() ) {
this->reset(); // version's forward compatibility
}
int version = 2;
this->load_and_save_data(version);
this->load_and_save_data(mBoardOrientation);
this->load_and_save_data(mBoardSize);
this->load_and_save_data(mComputerStarts);
this->load_and_save_data(mComputerInitialTurns);
if( version >= 2) {
this->load_and_save_data(mComputerTilesPerTurn);
}
this->load_and_save_data(mDebugFlags);
}
Simple and clear.
Of course, there are two methods (load() and save()) that are the outer interface and calls those here above, but: 1. They are part of a library (no need to rewrite them, OO as usual) and 2. The core of the load/save is written only once in load_save_data, with the advantage of simplicity, and having corresponding load and save code (types, order...).
Of course, there are cons, but I hope you'll see that it may make sense for some people to think that there are (IMHO very strong) pros as well.
The rest is a matter of taste.
I'm trying to make a function that returns a class (CTaxGroup) by taking as parameter a TaxGroupId.
The function will loop through a vector with an iterator.
int m_TaxGroupId;
CTaxGroup CTaxGroupVector::FetchTaxGroup(int TaxGroupId)
{
CTaxGroup l_TaxGroup;
std::vector<CTaxGroup>::iterator l_iterator =m_TaxGroupVector.begin();
for(l_iterator; l_iterator != m_TaxGroupVector.end(); l_iterator++)
{
int l_TaxGroupId = *l_iterator->GetTaxGroupId();
if(l_TaxGroupId == TaxGroupId)
{
l_TaxGroup = *l_iterator;
}
}
return l_TaxGroup;
}
std::vector<CTaxGroup> CTaxGroupVector::GetTaxGroupVector()
{
return m_TaxGroupVector;
}
At line 7, I get an error from my IDE (RAD Studio XE4) which states :
"E2062 Invalid indirection".
I know that it was something to do with the pointer, but I'm not sure what is my error.
I'm expecting that line 7 would return me an integer.
Without testing, since you don't provide a compilable program, it's likely that you should put parentheses around the initial dereferencing, (*l_iterator)->GetTaxGroupId(), so that the compiler knows you're trying to access a member of a CTaxGroup, not a member of an iterator.
i got some issues trying to convert my map into a set
I got a "Chanson" object with this member data :
std::map<std::string,Artiste*> m_interpretes;
Here is how i add my *Artiste to my map :
void Chanson::addArtiste(Artiste* a) throw (ExceptionArtiste, ExceptionLangueIncompatible)
{
if(a!=NULL)
{
if(a->getLangue() == this->getLangue())
{
m_interpretes.insert(pair<string, Artiste*>(a->getNom(), a));
//m_interpretes[a->getNom()] = a;
}
else
{
throw ExceptionLangueIncompatible(a,this);
}
}
}
set<Artiste*> Chanson::getArtistes() const
{
//set<Artiste*> machin;
return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());
}
i got this error due to this function :
Error C2664: 'std::pair<_Ty1,_Ty2> std::set<_Kty>::insert(Artiste *&&) : impossible de convertir le paramètre 1 de const std::pair<_Ty1,_Ty2> en 'Artiste *&&' c:\program files (x86)\microsoft visual studio 11.0\vc\include\set 179 1
Any idea how to fix it?
A map is an associative data structure, while a set only contains unordered collection of items, so adding a pair (key, value) is invalid for the latter and only holds for the former.
To make a set of keys from a map, you can do
std::set<Artiste*> tempSet;
std::transform(m_interpretes.cbegin(), m_interpretes.cend(),
std::inserter(tempSet, tempSet.begin()),
[](const std::pair<std::string, Artiste*>& key_value)
{ return key_value.second; });
return tempSet;
The std::set constructor you are trying to use will try to construct an element from everything the range you pass it:
return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());
But the element type of that range is
std::pair<const std::string, Artiste*>
which is definitely not convertible to Artiste*, which is why you are getting that error about not being able to convert. You could just do it manually though:
std::set<Artiste*> s;
for (const auto& pair : m_interpretes) {
s.insert(pair.second);
}
The problem is here:
return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());
If you have a look at the types you get from the map::begin() and map::end() functions you see that you get an iterator of std::pair<string, Artiste*>.
The problem is that the set::insert() function expects the iterators it is given to be of type Artiste*.
The simplest fix would be to create the set with a for loop, as shown in Barry's answer.
I'm currently hard at work on an assignment piece, which contains several custom datatypes. I've run into a problem where list is complaining that I am trying to remove a custom data type from a list of that same data type.
Error 3 error C2678: binary '==' : no operator found which takes a left-hand operand of type 'customer' (or there is no acceptable conversion) c:\program files (x86)\microsoft visual studio 10.0\vc\include\list 1194 1 Assignment 1 - Video Store MIS
The relevant code is here:
void customerCollection::removeCustomer(customer person)
{
customers.remove(person);
}
and the custom data type does have a == operator defined:
bool customer::operator==(customer &other) const
{
return (l_fullName == other.getName()) &&
(l_contactNumber == other.getNumber()) &&
(l_password == other.getPassword()) &&
(l_username == other.getUsername());
}
Is there any reason that the list type can't see the overloaded operator?
The customerCollection and customer data types are required parts of the program.
[EDIT] The overloaded operator is defined as public in the header file.
bool customer::operator==(customer &other) const
Try changing that to
bool customer::operator==(const customer &other) const
It is possible the code of the customers collection passes a const-qualified customer to the equality operator. At least, it is more idiomatic (and logical).
I'm inclined to say the reason is that the parameter is not const:
bool customer::operator==(const customer& other) const
depending on how remove is defined.