tinyXml2 causes error C2675 on build - xtree.cs - c++

I get the following three errors after building a project that uses tinyXml2. The errors are shown in the attached image. The offending code can be found in tinyXml2's xtree.cs file, here:
template<class _Iter>
void insert(_Iter _First, _Iter _Last)
{ // insert [_First, _Last) one at a time
_DEBUG_RANGE(_First, _Last);
for (; _First != _Last; ++_First)
{ // insert element as lvalue
const value_type& _Val = *_First;
insert(end(), _Val);
}
}
tinyXml2_Errors
I'm using (and must continue to use) VS2010
What could cause these errors?
1) error C2675: unary '++':'std::string' does not define this operator or a conversion to a type acceptable to the predefined operator
2) error C2100: illegal indirection
3)error C2440: 'initializing': cannot convert from 'std::string' to 'const std::pair<_Ty1,_Ty2> &'
Edit: included errors

I commented everything in the class (and header) and added code until I received the error. This failure was actually not due to tinyXml2 - it was a failure to insert a string into a map.
For anyone else who has this problem in the future, here is the offending function, which generates no squiggly red lines in Visual Studio.
map<string, string> createMap(CNintendoItem ni)
{
map<string, string> xmlNodeToValue;
//ItemName is a string constant. ni.Name is a string returned from a class
xmlNodeToValue.insert(ItemName, ni.Name);//name of the item
...//several more insertions
return xmlNodeToValue;
}
One way to fix this is to use the following method to assign a value to a new key:
xmlNodeToValue[ItemName] = ni.Name;//name of the item

Related

why can't i pass two different comparators to one template function?

I'm wracking my brain here for several hours, but I still don't understand why I'm getting an error when I'm trying to run this code.
After some time I managed to narrow it down to the expression:
pastryPrice()
which causes the problem - as you can see, I'm trying to build numerous comparators for one template function of sorting
struct dialingAreaComp{
inline bool operator()(const Deliver *d1, const Deliver *d2)const {
return d1->getDialingArea() < d2->getDialingArea();
}
};
struct pastryPrice {
inline bool operator()(const Pastry *p1, const Pastry *p2)const {
return p1->getPrice() < p2->getPrice();
}
};
template<class T>
void sortCollection(T& collection)
{
if ( typeid (collection) == typeid(vector <Deliver*>))
{
sort(collection.begin(), collection.end(), dialingAreaComp());
printCollection(collection);
}
else if (typeid (collection) == typeid(vector <Pastry*>))
{
sort(collection.begin(), collection.end(), pastryPrice());
printCollection(collection);
}
else { cout << "WRONG!"; }
}
I'm getting five errors, all the same:
Severity Code Description Project File Line Suppression State
Error C2664 'bool Bakery::pastryPrice::operator ()(const Pastry *,const Pastry *) const': cannot convert argument 1 from 'Deliver *' to 'const Pastry *' Bakery c:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility 809
And one more:
Severity Code Description Project File Line Suppression State
Error C2056 illegal expression Bakery c:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility 809
When I take off the expression I wrote above, the code works just fine - why can't I pass two different comparators to one template function?
Now:
C2264 is a Compiler Error that occurs when one tries to pass a function a parameter of an incompatible type.
But the Deliver function works and when I took off the Deliver comparator the Pastry compiled as well... so what is the incompatible type?
Your problem is both branches are compiled regardless of which one is taken.
I would approach this differently.
template<class A, class B>
struct overload_t:A,B{
using A::operator();
using B::operator();
overload_t(A a, B b):A(std::move(a)), B(std::move(b)){}
};
template<class A, class B>
overload_t<A,B> overload( A a, B b ){
return {std::move(a),std::move(b)};
}
This lets us overload two function objects or lambdas. (Perfect forwarding could be added, as can varargs..., but I kept it simple).
Now we simply:
auto comp=overload(dialingAreaComp{}, pastryPrice{});
using std::begin; using std::end;
std::sort( begin(collection), end(collection), comp );
and the compiler chooses the correct comparison function for us. Also flat array support while I was in there.
And stop using using namespace std;.
What the above code does is fuze your two function object tyoes into one. The using A::operator() and using B::operator() moves both () into the same class and tells C++ to pick between them when invoked using the usual method call overloading rules. The rest of the code is glue to deduce the types being overloaded and move-construct them.
sort calls () with objects of the compile-time determined type based on the type of the container. Overload resolution (within sort at the point of call) then picks the right body to compare at compile time.
Thus technique can be extended with support for more than 2 overloads, function pointers, and forwarding references. In C++17 some work can be done to have the overload type deduce its parent types, removing the need for the factory function.
You get an error because the templated function is evaluated at compile time, and one of the function calls will never match. Instead of the template use simple function overloads:
void sortCollection(vector <Deliver*>& collection)
{
sort(collection.begin(), collection.end(), dialingAreaComp());
printCollection(collection);
}
void sortCollection(vector <Pastry*>& collection)
{
sort(collection.begin(), collection.end(), pastryPrice());
printCollection(collection);
}

Map insert results in C2664 error in VS 2015, works in VS 2013

This piece of code was working perfectly in VS 2013 but I had to update to VS 2015 and now it throws an error.
I did read https://msdn.microsoft.com/en-us/library/s5b150wd.aspx and googled quite a bit however I still have no idea how to fix this.
I'm using eigen math library to do some 3d math stuff. Eigen's Vector3d class cannot be used as a key to containers so I created my own Vector3dLite class to get around this issue.
class Vector3dLite
{
public:
float VertX, VertY,VertZ;
Vector3dLite(Vector3d& InputVert)
{
VertX = static_cast<float>(InputVert.x());
VertY = static_cast<float>(InputVert.y());
VertZ = static_cast<float>(InputVert.z());
}
Vector3dLite(Vector3dLite& InputVert)
{
VertX = InputVert.VertX;
VertY = InputVert.VertY;
VertZ = InputVert.VertZ;
}
//more operator overloading stuff below
}
Here's where compiler throws the error
map<Vector3dLite, int> VertexIds;
int unique_vertid = 0;
VertexIds.insert(make_pair(Vector3dLite(tri.Vert1), unique_vertid)); //This line
// Vert1 is an eigen Vector3d object
//...
Here's the compiler error:
error C2664: cannot convert argument 1 from 'std::pair<Vector3dLite,int>' to 'std::pair<const _Kty,_Ty> &&'
with
[
_Kty=Vector3dLite,
_Ty=int,
_Pr=std::less<Vector3dLite>,
_Alloc=std::allocator<std::pair<const Vector3dLite,int>>
]
and
[
_Kty=Vector3dLite,
_Ty=int
]
I did try writing const before Vector3dLite object but apparently syntax is not correct.
VertexIds.insert(make_pair(const Vector3dLite(tri.Vert1), unique_vertid));
Since the value type for a map has const object as the first element (the map key), you generally can't use make_pair to construct the value, as the inferred type will not be const.
You can create a pair with explicit types:
std::pair<const Vector3dLite, int>(Vector3dLite(tri.Vert1), unique_vertid)
You can use the map's type
std::map<Vector3dLite, int>::value_type(Vector3dLite(tri.Vert1), unique_vertid)
Or you can create a named const object to use is make_pair
const Vector3dLite mapkey(tri.Vert1);
make_pair(mapkey, unique_vertid);
One other note: Your constructors should take their parameters by const &.

Can I assign/move a new value into a unique_ptr inside a tuple?

The need to do this has arisen since I want run to use all the other tuple elements. Basically, I have a vector of these tuples to form a kind of table. I couldn't figure out myself how to properly do this.
Edit: Apparently the previous, simplified code gives a different error, so ignore that. This code here is how I have it in my code. (Sorry)
class GUI {
using win_t = std::tuple<sf::RenderWindow&, Container&, std::unique_ptr<std::thread>, std::condition_variable>;
enum { WINDOW, CONT, THREAD, CV }
std::vector<win_t> windows;
void run(win_t &win);
win_t &addWindow(sf::RenderWindow & window, Container & c) {
windows.emplace_back(std::forward_as_tuple(window, c, nullptr, std::condition_variable()));
win_t &entry = windows.back();
std::get<GUI::THREAD>(entry) = std::make_unique<std::thread>(&GUI::run, this, entry); // error is on this line
return entry;
}
}
And the Error I'm getting:
Error C2280 'std::tuple<sf::RenderWindow &,Container &,std::unique_ptr<std::thread,std::default_delete<_Ty>>,std::condition_variable>::tuple(const std::tuple<sf::RenderWindow &,Container &,std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::condition_variable> &)': attempting to reference a deleted function dpomodorivs c:\program files (x86)\microsoft visual studio 14.0\vc\include\tuple 75`
Take a closer look at the error you're getting, substituting out the types:
Error C2280 'std::tuple<Ts...>::tuple(const std::tuple<Ts...>&)': attempting to reference a deleted function dpomodorivs c:\program files (x86)\microsoft visual studio 14.0\vc\include\tuple 75`
You're trying to use the copy constructor on your tuple, which is noncopyable (due to the unique_ptr and condition_variable). On that line, that is happening here:
std::make_unique<std::thread>(&GUI::run, this, entry)
Or more specifically, in the underlying std::thread constructor call. entry isn't copyable, but the thread constructor copies all of its arguments internally. Even if entry were copyable, this isn't want you want anyway since run() will then be called with a reference to thread's copy and not with the specific entry you want.
For that, you need std::ref():
std::make_unique<std::thread>(&GUI::run, this, std::ref(entry))

how to convert map into set

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.

C++ std::find lambda expressions

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.